C и C++: частичная инициализация автоматической структуры



например, если somestruct имеет три целых члена, я всегда думал, что это нормально, чтобы сделать это в C (или C++) функции:



somestruct s = {123,};


первый элемент будет инициализирован до 123, а последние два будут инициализированы до 0. Я часто делаю то же самое с автоматическими массивами, пишу int arr[100] = {0,}; Так что все числа в массиве инициализируются к нулю.





Недавно я прочитал в справочное руководство GNU C что:




Если вы не инициализируете переменную структуру, эффект зависит от
имеет ли он статическое хранилище (см. спецификаторы классов хранения) или
не. Если это так, то члены с целочисленными типами инициализируются с 0 и
элементы указателя инициализируются в значение NULL; в противном случае значение указателя
члены структуры неопределенны.






Может ли кто-нибудь сказать мне, что говорят стандарты C и C++ относительно частичной автоматической структуры и автоматической инициализации массива? Я делаю приведенный выше код в Visual Studio без проблем, но я хочу быть совместимым с gcc/g++, а может быть и с другими компиляторами. Спасибо

659   5  
c

5 ответов:

связанная документация gcc не говорит о Частичная Инициализация это просто говорит о (Полной)Инициализации или Нет Инициализации.

что такое частичная инициализация?

стандарты не определяют частичную инициализацию объектов, либо есть полная инициализация, либо нет-инициализация. Частичная инициализация-это нестандартная терминология что обычно относится к ситуации, когда вы предоставляете некоторые инициализаторы, но не все, т. е.: меньше инициализаторов, чем размер массива или количество инициализируемых элементов структуры.

пример:

int array[10] = {1,2};                    //Case 1:Partial Initialization

что такое (полная)инициализация или нет инициализации?

инициализация означает предоставление некоторого начального значения переменной, создаваемой одновременно с ее созданием. т. е.: в тот же оператор кода.

пример:

int array[10] = {0,1,2,3,4,5,6,7,8,9};    //Case 2:Complete Initialization
int array[10];                            //Case 3:No Initialization

цитируемый абзац описывает поведение для Case 3.

правила, касающиеся частичной инициализации(Case 1) также определено стандартом и эти правила не зависят от типа хранения переменной инициализируется.
Насколько мне известно, все основные компиляторы имеют 100% соответствие с настоящими Правилами.


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

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

Стандарт C99 6.7.8.21

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


в C++ Правила изложены с небольшой разницей.

C++03 Стандарт 8.5.1 Агрегаты
пункт 7:

если инициализаторов в списке меньше, чем членов в агрегате, то каждый член, явно не инициализированный, должен быть значение инициализации (8.5). [Пример:

 struct S { int a; char* b; int c; };
 S ss = { 1, "asdf" };

инициализирует ss.a С 1,ss.b С "asdf" и ss.c со значением выражения вида int(), то есть0. ]

в то время как инициализация значения определяется в,
В C++03 8.5 Инициализаторы
пункт 5:

до value-initialize объект типа T означает:
- если T-тип класса (пункт 9) с объявленным пользователем конструктором (12.1), то вызывается конструктор по умолчанию для T (и инициализация плохо сформирована, если T не имеет доступа конструктор по умолчанию);
- если T является тип класса non-union без объявленного пользователем конструктора, а затем каждый нестатический элемент данных и компонент базового класса T инициализируется значением;
- если T-тип массива, то каждый элемент инициализируется значением;
- в противном случае объект инициализируется нулем

в C, объекты никогда частично инициализированы - если какая-либо часть из них инициализирована, весь объект (и все подобъекты рекурсивно) инициализируются. Если явный инициализатор не предусмотрен, то элементы инициализируются до "нуля соответствующего типа".

цитата в вашем вопросе относится к тому, когда инициализатор для всего объекта полностью опущен, а не когда подобъекту не хватает инициализатора. Например, предполагая, что arr есть автоматическая продолжительность хранения, то это:

int arr[100] = { 123 };

инициализирует arr[0] до 123 и все остальные элементы arr до 0. Тогда как это:

int arr[100];

оставляет каждый элемент arr неинициализированное. Именно на этот последний случай ссылается цитата.

новейшие версии gcc также позволяют" частично " инициализировать и zeromem одновременно:

typedef struct{
  int a,b,c;
}T;

T s = {0, .b=5};

члены структуры теперь будут иметь следующие значения: a=0, b=5, c=0

у меня нет никакой информации о том, разрешают ли это другие компиляторы :p

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

Если переменная выделена в куче, компилятор также не инициализирует ее.

// You can use something like this:
typedef struct {

    ...;

    ...;

} somestruct;

// Declaration of struct
somestruct st;

// Initialising with 0. It does not depend on the size of the
// structure and the number of elements in it.
// memset() initialisation doesn't care if struct is static or dynamic.
// but don't forget to use st instead &st to dynamic.
memset(&st, 0, sizeof(somestruct));

Comments

    Ничего не найдено.