Разрешено ли вам изменять значение C, которое утверждает, что оно константное, если вы точно знаете, что оно на самом деле непостоянно?

Я столкнулся с более старым кодом в проекте, который объявляет struct в файле H как

struct A {
    const int i;  
};

Теперь функция, которая создает указатели на структуру A, выглядит так:

struct A * newStructA ( int i ) {
    struct B * ptr = malloc(sizeof(struct B));
    ptr->i = i;
    return (struct A *)ptr;
}

И struct B объявлен в файле C и выглядит так:

struct B {
    int i; 
};

Вопрос 1: Это даже разрешено в соответствии со стандартом C? Конечно, тип данных i один и тот же, и у struct должно быть такое же расположение памяти, но гарантируется ли это, или модификатор const также может изменить расположение памяти в некоторых системах?

Вопрос 2: Зная, что все struct A * указатели, с которыми имеет дело код, на самом деле являются struct B * указателями, можно ли будет привести указатели обратно к struct B *, а затем изменить значение int? В объявлении сказано, что это const, но я точно знаю, что это не так, поскольку он всегда находится в изменяемой динамической памяти. Или это может иметь последствия, поскольку компилятор C может полагаться на то, что значение является постоянным, поэтому он предполагает, что оно никогда не может измениться, и, таким образом, если две строки кода содержат ptr->i, компилятор может даже не получить значение во второй раз, поскольку как оно могло измениться? если это const? Так как это приведет к очень трудно отслеживаемым ошибкам, которые можно увидеть только при использовании определенного уровня оптимизации.

Вопрос 3: Есть ли лучший способ получить значение const, которое внешний код не может изменить напрямую (или, по крайней мере, никогда не должен пытаться), но внутренний код может измениться, поскольку значение на самом деле вовсе не const? Единственный способ, который я могу придумать, - это полностью скрыть макет структуры (struct A;), но тогда мне нужно предоставить функцию, подобную int getI(struct A * ptr), и всегда получать доступ к значению с помощью этой функции.

Разве это не должно быть 3 вопроса? Или два?

KamilCuk 16.02.2023 11:18

Почему struct A вообще существует? Поскольку типы A и B несовместимы, вы не должны обращаться к B через A в первую очередь.

user694733 16.02.2023 11:24

Возможно, «лучший» код для вашей функции newStructA (без хитроумного приведения): struct A temp = { i }; struct A* ptr = malloc(sizeof(struct A)); memcpy(ptr, &temp, sizeof(struct A)); return ptr;. Или вы можете передать адрес составного литерала в memcpy и избавиться от переменной temp: memcpy(ptr, &((struct A) { i }), sizeof(struct A));.

Adrian Mole 16.02.2023 11:29

@KamilCuk Но тогда мне пришлось бы дублировать все о вопросах три раза в трех разных вопросах и, таким образом, создавать вопросы, которые на 80% дублируют друг друга.

Mecki 16.02.2023 15:32
Руководство для начинающих по веб-разработке на React.js
Руководство для начинающих по веб-разработке на React.js
Веб-разработка - это захватывающая и постоянно меняющаяся область, которая постоянно развивается благодаря новым технологиям и тенденциям. Одним из...
Разница между Angular и React
Разница между Angular и React
React и AngularJS - это два самых популярных фреймворка для веб-разработки. Оба фреймворка имеют свои уникальные особенности и преимущества, которые...
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Калькулятор CGPA 12 для семестра
Калькулятор CGPA 12 для семестра
Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие...
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
О тренинге HTML JavaScript :HTML (язык гипертекстовой разметки) и CSS (каскадные таблицы стилей) - две основные технологии для создания веб-страниц....
Как собрать/развернуть часть вашего приложения Angular
Как собрать/развернуть часть вашего приложения Angular
Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?
1
4
94
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Проект 2011 года

6.7.3 Квалификаторы типа... 6 Если предпринимается попытка изменить объект, определенный с помощью типа с уточнением const, путем использования lvalue с неконстантный тип, поведение не определено. Если попытка будет сделано для ссылки на объект, определенный с типом volatile-qualified за счет использования lvalue с неизменяемым типом, поведение не определено.133) 133) Это относится к тем объектам, которые ведут себя так, они были определены с помощью уточненных типов, даже если на самом деле они никогда не определенные как объекты в программе (например, объект в отображенном в память входной/выходной адрес).

Я не думаю, что это применимо, поскольку объект получил свой эффективный тип путем присвоения неконстантного типа.

user694733 16.02.2023 11:20
modify an object defined Какой предмет? Где определили? Когда это было определено?
KamilCuk 16.02.2023 11:52
Ответ принят как подходящий
Разрешено ли вам изменять значение C, которое утверждает, что оно константное, если вы точно знаете, что оно на самом деле непостоянно?

Да.

Это даже разрешено в соответствии со стандартом C?

Да.

это гарантировано или модификатор const также может изменить расположение памяти в некоторых системах?

Возможно, при определении переменной как const переменная обычно помещается в другую область памяти, доступную только для чтения.

Зная, что все указатели на структуру A *, с которыми работает код, на самом деле являются указателями на структуру B *, будет ли разрешено привести указатели обратно к структуре B *, а затем изменить значение int?

Это неясно. Можете ли вы безопасно преобразовать структуру C с неконстантными членами в эквивалентную структуру с константными членами?

Или это может иметь последствия, поскольку компилятор C может полагаться на то, что значение является постоянным, поэтому он предполагает, что оно никогда не может измениться, и, таким образом, если две строки кода содержат ptr->i, компилятор может даже не получить значение во второй раз, как мог бы это изменилось, если это константа?

Да. Связанный https://stackoverflow.com/a/20707255/9072753 .

Есть ли лучший способ получить константное значение, которое внешний код не может изменить напрямую (или, по крайней мере, никогда не должен пытаться), но внутренний код может измениться, поскольку значение на самом деле вовсе не является константным?

Это C. Дух C говорит https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2086.htm :

(1) Trust the programmer.
(2) Don't prevent the programmer from doing what needs to be done.

На мой взгляд, лучше не прятаться, а просто использовать структуру с неконстантными членами. Программист на C в любом случае сможет получить к нему доступ.

Единственный способ, который я могу придумать, - это полностью скрыть макет структуры (struct A;), но тогда мне нужно предоставить такую ​​​​функцию, как int getI (struct A * ptr)

Да, скрытие чего-либо приведет к накладным расходам во время выполнения. FILE * был с нами всегда, и члены FILE видны для пользовательского кода во многих реализациях. При этом ими никто не пользуется.

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

Чтобы скрыть свой собственный код, используйте средства доступа и позвольте пользователям работать только с указателями на ваши данные с помощью идиомы PIMPL.

Что ж, "Доверяйте программисту" "устарело" согласно C11 и приведенной вами ссылке ;-) А учитывая, что 99,9999% всех ошибок вызваны программистом (а не компилятором, интерпретатором или оборудованием), все, что может предотвратить ошибки в первую очередь, наверное, хорошо. В конце концов, как вы указали, это не помешает программистам делать что-то преднамеренно, это просто помешает им сделать это случайно.

Mecki 21.02.2023 12:17

Другие вопросы по теме