объявление const struct - PullRequest
       35

объявление const struct

4 голосов
/ 04 октября 2011

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

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, как если бы они были определены с помощью:

const struct <typename> a, b, z;

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

Rich

Ответы [ 7 ]

4 голосов
/ 04 октября 2011

С:

const struct S
{
  uint8_t a;
};

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

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

struct S
{
  uint8_t a;
};
4 голосов
/ 04 октября 2011

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

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

2 голосов
/ 04 октября 2011

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

Что const делает:

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

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

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

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

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

2 голосов
/ 04 октября 2011
const struct S
{
  uint8_t a;
};

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

Это

const struct S
{
  uint8_t a;
} x;

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

0 голосов
/ 28 июля 2018

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

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

Если вы хотите, чтобы каждый экземпляр структуры был const, то есть его члены могут быть инициализированы только в той точке определения, которую вы можете сделать, как (используя 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

Заключение

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

0 голосов
/ 14 июня 2013

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

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

предупреждение: указатель бесполезного типа в пустом объявлении [включен по умолчанию]

0 голосов
/ 04 октября 2011

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

const var;

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

struct var;

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

...