инициализация агрегатов по умолчанию

0

Для следующей программы я не получаю предупреждение о том, что uoff.Reg и si используются без инициализации. gcc (с -Wextra) и clang (с -Weverything) оба не предупреждают, как я и ожидал.

#include<stdint.h>

typedef union {
  uint32_t Reg;
  struct {
    uint16_t Cx; 
    uint16_t sf; 
  };  
} tf; 

typedef struct {
  uint16_t i;
  uint16_t j;
} st; 

int bar(tf, tf);

int foo(tf t0, int32_t offset) {
  tf uoff;
  st s;
  t0.Reg = uoff.Reg + s.i + (uint32_t)offset;
  t0.sf = uoff.sf;
  return bar(t0, uoff);
}

Мне интересно, почему я не получаю предупреждения. Говорит ли стандарт (C/C++), что агрегаты с автоматическим хранилищем инициализируются (по умолчанию) до нуля или являются ли ограничения компилятора?

  • 3
    не могли бы вы упомянуть свой вопрос?
  • 0
    И что? Компилятору не требуется искать ошибки в вашем коде - вы
Показать ещё 2 комментария
Теги:
initialization
gcc
compiler-warnings

4 ответа

3
Лучший ответ

Я проверил gcc:: http://coliru.stacked-crooked.com/a/f1b25f7f369fbdbc, и предупреждения генерируются

вот как он компилируется:

g++ - 4.8 -std = С++ 11 -O2 -Wall -pedantic -pthread main.cpp &&./a.out

и выход:

main.cpp:10:3: warning: ISO C++ prohibits anonymous structs [-Wpedantic]    
   };      
   ^    
main.cpp: In function 'int foo(tf, int32_t)':    
main.cpp:23:21: warning: 'uoff.tf::Reg' is used uninitialized in this function -Wuninitialized]

   t0.Reg = uoff.Reg + s.i + (uint32_t)offset;    
                     ^    
main.cpp:23:21: warning: 's.st::i' is used uninitialized in this function -Wuninitialized]

/tmp/ccIy8fGt.o: In function 'foo(tf, int)':    
main.cpp:(.text+0xa): undefined reference to 'bar(tf, tf)'    
collect2: error: ld returned 1 exit status
2

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

st s = st(); // C++03 and C++11
st s = {};   // C++03 and C++11
st s{};      // C++11

Компиляторы не обязаны предупреждать вас о переменных uninitializad. Тем не менее, минимальный набор флагов компиляции, необходимых для получения предупреждения с g++, кажется,

-Wuninitialized -O2

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

1

Нет, C-Standard не требует от компилятора генерировать код для инициализации автоматических переменных. Чтение их значения без предварительной инициализации провоцирует неопределенное поведение.

Однако этот код

int main(void)
{
  int a;
  int b = a;
  b = b;

  return 0;
}

скомпилированный с использованием опции gcc -Wall, дает:

main.c:4: warning: ‘a is used uninitialized in this function

[gcc (Debian 4.4.5-8) 4.4.5]

1

Указывает ли стандарт (C/C++), что агрегаты с автоматическим хранением инициализируются (по умолчанию) до нуля

Нет, нет. Автоматические переменные не инициализируются, их значение изначально остается неопределенным. Использование их без инициализации приводит к неопределенному поведению.

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню