Присваивание массивов

Каждый ребенок знает, что массивы и указатели в Си — это не одно и то же. Я обязательно посвящу этому волнующему вопросу один из будущих постов, но сейчас существенно то, что имя массива не может выступать в качестве lvalue. Попросту говоря — массиву нельзя ничего присвоить, поскольку его адрес определяется при компиляции; единственное исключение — первоначальная инициализация, вроде такой:

int a[5] = { 1, 2, 3, 4, 5 };

Если же мы попробуем провернуть такой же фокус в дальнейшем:

15
16
17
int a[3] = { 1, 2, 3 };
int b[3] = { 3, 2, 1 };
a = b;

получим по сусалам от компилятора:

$ cc -o0 -g -o test test.c
test.c: In function 'main':
test.c:17: error: incompatible types in assignment

Казалось бы, типы одинаковые: int[3], но нет, не дают присвоить. Такой вот семантический парадокс.
Но это еще не самое интересное. Самое интересное — массивы таки можно присвоить (читай — скопировать), безо всяких memcpy. Вот глядите:

struct s_tag {int arr[100];} aa, bb;
int i;
for (i = 0; i < 100; i++)
    aa.arr[i] = i;
bb = aa;

Все прекрасно компилируется и работает, и именно так, как предполагалось: один массив копируется в другой, цикл копирования генерируется компилятором.

Стоит добавить к этому, что при передаче массива в качестве аргумента функции копирование не происходит — передается только адрес. Зато если массив обернуть в структуру и передать ее по значению функции — копируется.

Мораль: массивы — это не совсем указатели и не совсем массивы; во избежание недоразумений необходимо учить матчасть.

УжасноПлохоНормальноХорошоОтлично (6 голосов, средний: 4,50 из 5)
Loading ... Loading ...

Оставьте свой отзыв

Или введите OpenId:

XHTML: Можно использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">