Как вы сравниваете два случая структур на равенство в стандарте C?
216
C не предоставляет никаких языковых возможностей для этого - вы должны сделать это сами и сравнить каждого члена структуры с каждым членом.
0.0, -0.0 NaN
проблемойmemcmp()
. Указатели, которые отличаются в двоичном представлении, могут указывать на одно и то же местоположение (например, DOS: seg: offset) и, следовательно, равны. Некоторые системы имеют несколько нулевых указателей, которые сравниваются одинаково. То же самое для неясныхint
типов с -0 и типов с плавающей запятой с избыточным кодированием. (Intel long double, decimal64 и т. Д.) Эти проблемы не имеют значения,calloc()
используется или нет или заполнение.==
не работает со структурами (как я), пожалуйста , см stackoverflow.com/questions/46995631/...Вы можете испытать желание использовать
memcmp(&a, &b, sizeof(struct foo))
, но это может не работать во всех ситуациях. Компилятор может добавить буферное пространство выравнивания в структуру, и значения, найденные в ячейках памяти, лежащих в буферном пространстве, не обязательно будут каким-либо конкретным значением.Но, если вы используете
calloc
илиmemset
полный размер структур перед их использованием, вы можете выполнить поверхностное сравнение сmemcmp
(если ваша структура содержит указатели, она будет совпадать, только если адрес, на который указывают указатели, одинаков).источник
memcmp
условии, что память была очищена первой. Что близко к работе, но не правильно. Конечно, вопрос также не определяет «равенство», поэтому, если вы понимаете, что это означает «побайтовое равенство представления объекта», тоmemcmp
именно это и делает (очищается память или нет).Если вы делаете это много, я бы предложил написать функцию, которая сравнивает две структуры. Таким образом, если вы когда-нибудь измените структуру, вам нужно изменить сравнение только в одном месте.
Что касается того, как это сделать .... Вам нужно сравнить каждый элемент в отдельности
источник
Вы не можете использовать memcmp для сравнения структур на равенство из-за возможных случайных символов заполнения между полями в структурах.
Выше не получится для такой структуры:
Вы должны использовать сравнение для каждого члена, чтобы быть в безопасности.
источник
@ Грег правильно, что нужно написать явные функции сравнения в общем случае.
Можно использовать,
memcmp
если:NaN
.-Wpadded
для проверки clang) ИЛИ структуры явно инициализируютсяmemset
при инициализации.BOOL
), которые имеют различные, но эквивалентные значения.Если вы не программируете для встраиваемых систем (или пишете библиотеку, которая может быть использована на них), я бы не стал беспокоиться о некоторых ключевых случаях в стандарте C. Различение ближнего и дальнего указателя не существует ни на одном 32- или 64-разрядном устройстве. Ни одна не встроенная система, о которой я знаю, не имеет нескольких
NULL
указателей.Другой вариант - автоматически генерировать функции равенства. Если вы выложите свои определения структуры простым способом, можно использовать простую обработку текста для обработки простых определений структуры. Вы можете использовать libclang для общего случая - поскольку он использует тот же внешний интерфейс, что и Clang, он правильно обрабатывает все угловые случаи (за исключением ошибок).
Я не видел такой библиотеки генерации кода. Однако это выглядит относительно просто.
Тем не менее, это также тот случай, когда такие сгенерированные функции равенства часто делают неправильные вещи на уровне приложения. Например, следует
UNICODE_STRING
ли сравнивать две структуры в Windows поверхностно или поверхностно?источник
memset
и т. Д. Не гарантирует значение битов заполнения после дальнейшей записи в элемент структуры, см .: stackoverflow.com/q/52684192/689161Обратите внимание, что вы можете использовать memcmp () для нестатических структур, не беспокоясь о заполнении, если вы не инициализируете все элементы (сразу). Это определяется C90:
http://www.pixelbeat.org/programming/gcc/auto_init.html
источник
{0, }
также будет обнулять любые байты заполнения?Это зависит от того, является ли вопрос, который вы задаете:
Чтобы выяснить, являются ли они одним и тем же объектом, сравните указатели с двумя структурами равенства. Если вы хотите узнать в общем, имеют ли они одинаковое значение, вы должны сделать глубокое сравнение. Это включает в себя сравнение всех членов. Если участники являются указателями на другие структуры, вам также необходимо участвовать в этих структурах.
В особом случае, когда структуры не содержат указателей, вы можете сделать memcmp, чтобы выполнить побитовое сравнение данных, содержащихся в каждом, без необходимости знать, что эти данные означают.
Убедитесь, что вы знаете, что означает «равно» для каждого члена - это очевидно для целых чисел, но более тонко, когда речь идет о значениях с плавающей запятой или пользовательских типах.
источник
memcmp
не сравнивает структуру,memcmp
сравнивает двоичный файл, и в структуре всегда есть мусор, поэтому он всегда выдает False в сравнении.Сравните элемент за элементом, это безопасно и не терпит неудачу.
источник
Если структуры содержат только примитивы или если вы заинтересованы в строгом равенстве, вы можете сделать что-то вроде этого:
Однако, если ваши структуры содержат указатели на другие структуры или объединения, вам нужно написать функцию, которая правильно сравнивает примитивы и при необходимости выполняет сравнения с другими структурами.
Имейте в виду, однако, что вы должны были использовать memset (& a, sizeof (struct my_struct), 1), чтобы обнулить диапазон памяти структур как часть вашей инициализации ADT.
источник
если переменная 2 структурам инициализирована с помощью calloc, или они установлены в 0 с помощью memset, так что вы можете сравнить свои 2 структуры с memcmp, и вам не нужно беспокоиться о мусоре структуры, и это позволит вам заработать время
источник
В этом совместимом примере используется расширение компилятора #pragma pack из Microsoft Visual Studio для обеспечения максимально плотной упаковки элементов структуры:
источник