C и C++: частичная инициализация автоматической структуры
например, если somestruct имеет три целых члена, я всегда думал, что это нормально, чтобы сделать это в C (или C++) функции:
somestruct s = {123,};
первый элемент будет инициализирован до 123, а последние два будут инициализированы до 0. Я часто делаю то же самое с автоматическими массивами, пишу int arr[100] = {0,}; Так что все числа в массиве инициализируются к нулю.
Недавно я прочитал в справочное руководство GNU C что:
Если вы не инициализируете переменную структуру, эффект зависит от
имеет ли он статическое хранилище (см. спецификаторы классов хранения) или
не. Если это так, то члены с целочисленными типами инициализируются с 0 и
элементы указателя инициализируются в значение NULL; в противном случае значение указателя
члены структуры неопределенны.
Может ли кто-нибудь сказать мне, что говорят стандарты C и C++ относительно частичной автоматической структуры и автоматической инициализации массива? Я делаю приведенный выше код в Visual Studio без проблем, но я хочу быть совместимым с gcc/g++, а может быть и с другими компиляторами. Спасибо
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