Я привык, что структуры можно сравнивать с помощью memcmp(). Сегодня нарвался на неприятность.
Вот кусок программы (без проверок кодов возврата, чтоб понятнее было):
struct termios ios, ios2;
tcgetattr(scfd, &ios);
// тут меняем флажочки в ios
tcsetattr(scfd, TCSANOW, &ios);
// (1)
tcgetattr(scfd, &ios2);
if( memcmp(&ios, &ios2, sizeof(ios)) != 0) {
fprintf(stderr,"Warning: not all parameters successfully set by tcsetattr()\n");
}Стабильно получаю это сообщение об ошибке.
Печатаю все элементы ios и ios2 поштучно - всё нормально, совпадают.
После десяти минут поисков ошибки в программе и в своей ДНК, начинаю печатать уже побайтно.
Обнаруживаю стабильное несовпадение в 49-51 байтах. Ага, это всё от выравнивания по границе слова.
Попробовал в точку (1) добавить ios2=ios1. Помогло.
Структура выглядит так:
typedef unsigned char cc_t;
typedef unsigned int speed_t;
typedef unsigned int tcflag_t;
#define NCCS 32
struct termios
{
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};Несовпадающие байты - это вовсе даже не в конце, а в середине. После c_cc (начинается со смещения 17 и заканчивается на 48) и перед c_ispeed (смещение 52).
На данной конкретной архитектуре i386 структура копируется не поэлементно, а с помощью rep movsl, но это implmentation dependent. На PowerPC в этом месте вызывается memcpy(&ios2,&ios,60). А вообще говоря, никто этого не обещал.
Так что же, структуры таки надо всегда сравнивать поэлементно, или стандарт предусматривает при копировании структур и копирование всех байтов в пределах sizeof()?
Tags:
no subject
Изначально речь шла о C, а не о C++.