Если у меня есть две структуры C, инициализированные одинаковыми членами, могу ли я гарантировать, что:
memcmp(&struct1, &struct2, sizeof(my_struct))
всегда будет возвращать нуль?
Если у меня есть две структуры C, инициализированные одинаковыми членами, могу ли я гарантировать, что:
memcmp(&struct1, &struct2, sizeof(my_struct))
всегда будет возвращать нуль?
Я не думаю, что вы можете безопасно memcmp
создать структуру для проверки равенства.
Из C11 §6.2.6.6 Представления типов
Когда значение хранится в объекте структуры или типа объединения, в том числе в объекте-члене, байты представления объекта которые соответствуют любым байтам заполнения, принимают неопределенные значения.
Это означает, что вам нужно будет написать функцию, которая сравнивает отдельные элементы структуры
int my_struct_equals(my_struct* s1, my_struct* s2)
{
if (s1->intval == s2->intval &&
strcmp(s1->strval, s2->strval) == 0 &&
s1->binlen == s2->binlen &&
memcmp(s1->binval, s2->binval, s1->binlen) == 0 &&
...
) {
return 1;
}
return 0;
}
Нет, две структуры со всеми равными членами могут иногда не сравнивать равные для memcmp()
, из-за padding.
Один из правдоподобных примеров заключается в следующем. Для инициализации st2
32-разрядный компилятор, соответствующий стандарту, может генерировать последовательность инструкций по сборке, которые оставляют часть окончательного дополнения неинициализированной. Эта часть дополнения будет содержать все, что попадало в стек, в то время как st1
заполнение обычно содержит ноль:
struct S { short s1; long long i; short s2; } st1 = { 1, 2, 3 };
int main() {
struct S st2 = { 1, 2, 3 };
... at this point memcmp(&st1, &st2, sizeof(struct S)) could plausibly be nonzero
}
Если обе переменные являются глобальными или статическими, а их члены были инициализированы во время инициализации программы, то да, они будут сравнивать равные с (Примечание. Большинство систем просто загружают страниц данных на нулевые инициализированные страницы, но стандарт C не гарантирует этого.)memcmp()
.
Кроме того, если одна из структур была инициализирована другой с помощью memcpy()
, то они будут сравнивать равные с memcmp()
.
Если оба элемента были инициализированы до некоторого общего значения с помощью memset()
, прежде чем их члены будут инициализированы одинаковыми значениями, тогда они также сравнятся с memcmp()
(если их члены также не являются структурами, то те же ограничения применяются рекурсивно).
Помимо очевидного случая заполнения структуры, он даже не гарантируется для отдельных переменных. См. Сноску 6.2.6.1 (8):
Объекты
x
иy
возможны с тем же эффективным типомT
иметь одинаковое значение, когда к ним обращаются как объекты типаT
, но иметь разные значения в других контекстах. В частности, если==
определяется для типаT
, тоx == y
не означает, чтоmemcmp(&x, &y, sizeof (T)) == 0
. Кроме того,x == y
не обязательно следует, чтоx
иy
имеют одинаковое значение; Другие операции над значениями типаT
могут различать их.
Вы можете гарантировать, что они идентичны, если вы убедитесь, что оба целых блока памяти инициализированы до их заполнения, например. с memset
:
memset(&struct1, 0, sizeof(my_struct))
EDIT, оставив это здесь, потому что поток комментариев полезен.