объявление константной структуры

Может ли кто-нибудь сказать мне разницу между этими двумя версиями объявления структуры?

struct S
{
  uint8_t a;
};

и

const struct S
{
  uint8_t a;
}

С последующим:

void main(void)
{
  struct S s = {1};
  s.a++;
}

Подсказка: я пробовал обе версии для S в Visual Studio C++ 2010 Express, поэтому знаю, что обе компилируются с ошибками.

Неужели "const struct" вообще ничего не делает? "const struct S s = {1};" конечно, но это не проблема в данный момент.

С уважением Рич

/********************************************/

Я только что понял, что

const struct <typename> <{type}> <variable instances a, b, .., z>;

делается:

Когда const присутствует перед "struct", все экземпляры переменных являются константами, как если бы они были определены с помощью:

const struct <typename> a, b, z;

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

Богатый


person RichColours    schedule 04.10.2011    source источник
comment
В конце второго отсутствует точка с запятой, что означает, что вы указали два разных типа в том месте, где принадлежит возвращаемый тип main. Ни один из этих типов не является тем, чем должен быть -- int. Я не могу вспомнить, разрешено ли вам определять тип в определении функции (и в любом случае не совсем понятно, на каком языке вы компилируете этот код), это может быть дополнительной ошибкой.   -  person Steve Jessop    schedule 04.10.2011
comment
Кроме void main(), какие еще проблемы существуют @KerrekSB   -  person Luchian Grigore    schedule 04.10.2011
comment
Извините за C++, я удалил свой комментарий. @Rich: во втором фрагменте отсутствует точка с запятой, а void main(void) не разрешено.   -  person Kerrek SB    schedule 04.10.2011
comment
Есть ли шанс, что вы могли бы показать нам код, с которым вы на самом деле работаете. Отсутствие точки с запятой заставляет меня думать, что могут быть и другие проблемы.   -  person David Heffernan    schedule 04.10.2011
comment
Отсутствие точки с запятой связано с тем, что я набрал ее от руки. Это не проблема здесь. @SteveJessop это PHP (сарк)   -  person RichColours    schedule 04.10.2011
comment
Я не говорю чушь, когда сказал, что скомпилировал void main(void) в VC++ 2010. Попробуйте, прежде чем говорить мне второй раз, что это не работает.   -  person RichColours    schedule 04.10.2011
comment
@Rich: Я имею в виду, что не совсем ясно, действительно ли вы компилируете его как C или C++. Учитывая различные ошибки в вашем вопросе, один только тег C не вселяет в меня уверенность. Керрек не сказал, что это не работает, он сказал, что это не разрешено. Он имел в виду на языке, и это правда, будь то C или C++.   -  person Steve Jessop    schedule 04.10.2011


Ответы (7)


С:

const struct S
{
  uint8_t a;
};

Квалификатор const не имеет смысла и может даже вызвать ошибку компиляции с некоторыми компиляторами C. gcc выдает предупреждение.

Похоже, намерение состоит в том, чтобы объявить тип данных struct S. В этом случае правильный синтаксис:

struct S
{
  uint8_t a;
};
person Daniel Trebbien    schedule 04.10.2011
comment
Спасибо, мой VC не выдал предупреждения, как и мой компилятор Motorola HS12 об этом. Он возник в результате работы над каким-то встроенным кодом. Я подумал, что вернусь к VC и проверю свои выводы по объявлению const struct. Я попробую это в gcc! - person RichColours; 04.10.2011

Объявление структуры просто определяет тип данных.

Спецификатор const относится к переменной, а не к типу данных. Таким образом, добавление const перед объявлением структуры должно быть в лучшем случае избыточным.

person Alok Save    schedule 04.10.2011
comment
Я думаю, что это +1 из-за различия между типами и квалификаторами, что здесь важно. - person Kerrek SB; 04.10.2011

const struct S
{
  uint8_t a;
};

не является допустимой конструкцией.

Этот

const struct S
{
  uint8_t a;
} x;

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

person Tony The Lion    schedule 04.10.2011
comment
Точка с запятой в конце структуры была случайностью. Я определяю свои s в main() не встроенными в объявление структуры. - person RichColours; 04.10.2011
comment
На самом деле, я только что попробовал const struct S { uint8_t a; }; в VC, и он скомпилирован без указания имен экземпляров переменных. Так что, возможно, нам всем нужно проверить наши песенники, прежде чем публиковать X неправильно в чьем-то посте. - person RichColours; 04.10.2011

Квалификатор const применяется к переменным или членам. Чтобы создать экземпляр переменной const, просто укажите const во время создания экземпляра.

Что делает const:

  • во время компиляции убедитесь, что для константных переменных выполняется только чтение
  • если переменная const создается со значением, которое может быть разрешено во время компиляции, поместите переменную в память программы

Когда const применяется к членам, например:

struct T {
    int const i;
    int j;
};

Вы можете (законно) присвоить значение i только при создании структуры. Вы можете изменить значение const (если память программы находится в ОЗУ, а не в ПЗУ), приведя его к неконстантному типу (const-cast), но этого делать не следует. делать.

Типичное использование const-cast - это когда вы используете библиотеку, которая не указывает константность в объявлениях функций, а ваш код делает это. На данный момент, если вы хотите использовать его, вы должны доверять ему и передавать параметры перед вызовом его функций.

person cJ Zougloub    schedule 04.10.2011

Когда вы объявляете

const var;

затем он выделяет для него некоторое пространство памяти, но

struct var;

это было просто объявление, компилятор не выделяет для него места. поэтому он показывает ошибку, а в структуре const вы не объявляли какую-либо переменную, см. код, поэтому он показывает ошибку.

person Gouse Shaik    schedule 04.10.2011

Бессмысленно использовать ключевое слово const перед struct.

Если вы используете компилятор gcc, он показывает следующее предупреждение:

предупреждение: бесполезный квалификатор типа в пустой декларации [включен по умолчанию]

person Varun Chhangani    schedule 14.06.2013

Это единственное использование, о котором я могу думать:

const struct S {
        int a;
        int b;
} s;

Это объявляет структуру и немедленно создает для нее экземпляр с именем s, и в этот момент a и b в s инициализируются 0 (обратите внимание, что в этот момент s является глобальной переменной в единице перевода, в которой она была объявлена, и могут быть связаны извне).

printf("a = %d\t b = %d\n", s.a, s.b); // a = 0     b = 0

Если вы попытаетесь установить элементы s, вы потерпите неудачу:

s.a = 1; //error: assignment of member ‘a’ in read-only object

Итак, s здесь не очень полезен... если только вы не сделаете что-то вроде:

const struct S {
        int a;
        int b;
} s =  { 1, 2 };

Теперь давайте создадим еще один экземпляр той же структуры (объявление такое же, как и выше):

    struct S other;
    other.a = 1;
    other.b = 2;

    printf("a = %d\t b = %d\n", other.a, other.b); // a = 1     b = 2

Компилятор больше не будет жаловаться, так как other не константа! только s является константой!

Вы можете спросить, что же делают эти const? попробуем изменить s:

s = other; // error: assignment of read-only variable ‘s’

Вот и все. Если вам не нужно, чтобы компилятор выделял память для s в момент объявления, и вам по-прежнему нужно, чтобы экземпляр s был константным, вы просто добавили бы const в момент создания экземпляра struct S (обратите внимание на заглавную букву S!!)

Бонус 1

const struct S {
        int a;
        int b;
};

обратите внимание, что маленького s больше нет. В этот момент GCC предупредит вас, что квалификатор const ничего не делает!!!!

Бонус 2

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

typedef const struct S {
        int a;
        int b;
} s;

// The wrong way
s thisIsAnS;
thisIsAnS.a = 1; //error: assignment of member ‘a’ in read-only object 

// The correct way
s thisIsAnS = { 1 , 2 }; //compiles fine, but you can not change a or b anymore

Заключение

Для меня это просто синтаксический сахар, который только усложняет код. Но кто я такой, чтобы судить...

person Saeid Yazdani    schedule 28.07.2018