воскресенье, 18 октября 2009 г.

Do not use & for arrays

Представьте, что вам попался код следующего вида:
typedef unsigned char Str255[257];
Str255 Blah;

void f( Str255 s )
{
  memcpy(&Blah, &s, sizeof(Str255)); // error here
}

int main()
{
  Str255 x("Blah");
  f( x );
}
Вопрос в том, почему данный код будет работать неверно, т.е. в Blah будет скопировано не содержимое x, а непонятный мусор? Ошибка тут в том, что в memcpy не нужно использовать &, а писать memcpy(Blah, s, sizeof(Str255));. Потому что s и &s — это разные указатели, и они даже имеют разный тип: unsigned char * and unsigned char (*)[257] соответсвенно. Обычно указатель на первый элемент массива и указатель на массив — это одно и тоже, но в нашем случае это не так. Посмотри как выглядит функция f, если не использовать typedef:
void f( unsigned char* s )
{
  memcpy(&Blah, &s, sizeof(Str255)); // error here
}
При вызове этой функции, в соответсвии с пунктом 4.2 стандарта C++, массив будет неявно преобразован в указатель и мы получим, что s указывает на массив с текстом, но &s будет указывать на указатель, который хранится на стеке, т.е. при копировании мы получим содержимое стека в Blah. Чтобы избежать такого недоразумения лучше использовать std::string в C++, ну а в C просто не использовать typedef для строк и понимать что происходит.

Комментировать в ВКонтакте