Я привык, что структуры можно сравнивать с помощью 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
no subject
no subject
no subject
cld movl $15, %ecx leal -152(%ebp), %edi leal -88(%ebp), %esi rep movslP.S. Если там вместо присваивания написать memcpy и включить -O, то получается ровно то же самое :) А если -O не писать, тогда честно вызывается memcpy.
no subject
no subject
Там в труктуры ты бы перекрыл интерфейс IComparable и она бы сравнивалась так, как реализовано в твоём методе.
А вот такое байт вообще лучше забыть, если оперируешь с абстракциями.
А в C++ приходится помнить и что такое стэк, и что такое регистр, и даже что такое деструктор.
no subject
no subject
Но и без мака у C++ ещё много применений пока.
Я к тому что используя C++ нужно быть готовым к машинным ньюансам.
no subject
Изначально речь шла о C, а не о C++.