Как обрабатываются постоянные члены структуры в C? - PullRequest
2 голосов
/ 19 июня 2020

Можно, сделать что-то подобное?

struct MyStruct {
    int x;
    const char y; // notice the const
    unsigned short z;
};
struct MyStruct AStruct;
fread(&MyStruct, sizeof (MyStruct), 1,
      SomeFileThatWasDefinedEarlierButIsntIncludedInThisCodeSnippet);

Я изменяю постоянный член структуры, записывая всю структуру из файла. Как с этим справиться? Это неопределенное поведение для записи в непостоянную структуру, если один или несколько членов структуры постоянны? Если да, то какова общепринятая практика обработки постоянных членов структуры?

Ответы [ 3 ]

3 голосов
/ 19 июня 2020

Это неопределенное поведение.

Черновик C11 n1570 говорит:

6.7.3 Квалификаторы типов

...

.. .

Если предпринята попытка изменить объект, определенный с помощью типа с квалификацией const, посредством использования lvalue с типом, не определенным с помощью const, поведение не определено.

Моя интерпретация этого такова: чтобы соответствовать стандарту, вам разрешено устанавливать значение члена const только во время создания объекта (он же инициализация), например:

struct MyStruct AStruct = {1, 'a', 2};  // Fine

Doing

AStruct.y = 'b';   // Error

должен выдать ошибку компилятора.

Вы можете обмануть компилятор с помощью такого кода:

memcpy(&AStruct, &AnotherStruct, sizeof AStruct);

Вероятно, он будет нормально работать в большинстве систем, но это все еще неопределенное поведение в соответствии с C11 стандарт.

См. также memcpy с указателем назначения на данные const

2 голосов
/ 19 июня 2020

Как элементы константной структуры обрабатываются в C?

Прочтите стандарт C11 n1570 и его §6.7.3, связанный с квалификатором const .

Если да, то какова общепринятая практика обработки постоянных элементов структуры?

Это зависит от того, заботитесь ли вы больше о строгом соответствии стандарту C или о практических реализациях. См. этот черновой вариант отчета (работа ведется в июне 2020 г.), где обсуждаются эти проблемы. Такие соображения зависят от усилий по разработке, направленных на ваш проект, и от переносимости вашего программного обеспечения (на другие платформы).

Вероятно, вы не потратите те же усилия на встроенное программное обеспечение респиратора Covid (или внутри какого-нибудь ICBM ) и на веб-сервер ( например lighttpd или библиотека, такая как libonion или какое-то приложение FastCGI ) внутри дешевого бытового устройства или работающая на дешевом арендованном Linux VPS .

Также рассмотрите возможность использования инструментов анализа c, таких как Frama- C или Clang stati c анализатора в вашем коде.

Что касается неопределенного поведения, обязательно прочтите этот блог .

См. Также этот ответ на связанный вопрос.

Я изменяю постоянный член структуры, записывая всю структуру из файла.

Тогда важны проблемы endianness и файловой системы . Рассмотрите возможность использования библиотек, связанных с JSON, YAML , возможно, смешанными с sqlite или PostGreSQL или TokyoCab inet (и исходный код всех этих библиотек с открытым исходным кодом или из Linux ядра может быть вдохновляющим).

0 голосов
/ 23 июня 2020

Стандарт немного неаккуратен в своем определении и использовании термина «объект». Чтобы такое утверждение, как «Все X должны быть Y» или «X не может быть Z» было значимым, определение X должно иметь критерии, которые не только удовлетворяются всеми X, но и однозначно исключают все объекты, которые не являются должны быть Y или могут быть Z.

Однако определение «объекта» - это просто «область хранения данных в среде выполнения, содержимое которой может представлять значения». Такое определение, однако, не проясняет, всегда ли каждый возможный диапазон последовательных адресов является «объектом», или когда различные возможные диапазоны адресов подчиняются ограничениям, которые применяются к «объектам», а когда это не так.

Для того чтобы Стандарт мог однозначно классифицировать крайний случай как определенный или неопределенный, Комитету необходимо достичь консенсуса относительно того, следует ли его определять или не определять. Если члены Комитета принципиально расходятся во мнениях относительно того, следует ли определять некоторые случаи или не определять их, единственный способ принять правило консенсусом будет заключаться в том, чтобы правило было написано двусмысленно таким образом, чтобы позволить людям с противоречивыми взглядами на то, что следует определять каждому, правило поддерживает их точку зрения. Хотя я не думаю, что члены Комитета явно хотели сделать свои правила двусмысленными, я не думаю, что Комитет мог прийти к консенсусу в отношении правил, которых не было.

Учитывая эту ситуацию, многие действия, включая обновление структуры, которые имеют постоянные члены, скорее всего, попадают в сферу действий, реализация которых не требует значимой обработки в стандарте, но которые авторы стандарта ожидали бы, что реализации будут осмысленно обрабатываться в любом случае.

...