Использование неинициализированной переменной без вызова неопределенного поведения - PullRequest
2 голосов
/ 15 октября 2019

Начиная с 6.3.2.1 (выделено мной)

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

Это означает, что если автоматический объектне может быть объявлено с классом хранилища регистров (если его адрес занят):

int x; 

printf("just a dummy pointer print %p", &x);  //taking the address to break 6.3.2.1 UB condition

if (x == 2)
{
    print("x uninitialized value: %d", x);
} 

Чем в соответствии с 6.3.2.1 нет неопределенного поведения в if (x == 2), где я использую значение неинициализированного объекта. Если это правда, и здесь нет UB, то каково определенное поведение? что я должен ожидать в x в соответствии со стандартом?

Ответы [ 2 ]

2 голосов
/ 15 октября 2019

В этом случае, поскольку x получил адрес, поведение не является строго неопределенным. Значение x в этой точке равно неопределенно . Это означает, что значением является либо представление ловушки , либо неопределенное .

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

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

Соответствующие отрывки из C стандарта :

Раздел 3.19:

3.19.2

1 неопределенное значение либо неопределенное значение, либо представление ловушки

3.19.3

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

2 ПРИМЕЧАНИЕ Не указанозначение не может быть представлением прерывания.

3.19.4

1 представление прерывания представление объекта, которое не нужно представлятьзначение типа объекта

Раздел 6.7.9p10:

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

1 голос
/ 15 октября 2019

Стандарт использует термин «неопределенное поведение», среди прочего, для описания общих ситуаций, когда подавляющее большинство реализаций будет вести себя одинаково предсказуемо, но где некоторые конкретные реализации могут лучше обслуживать своих клиентов, ведя себя по-разному.

Рассмотрим следующую функцию:

struct foo { unsigned char dat[256]; };

struct foo x,y;

void test(int a, int b)
{
  struct foo temp;
  temp.dat[a] = 1;
  temp.dat[b] = 2;
  x=temp;
  y=temp;
}

Не думаю, что авторы Стандарта хотели требовать, чтобы программисты полностью инициализировали temp перед его сохранением, но я также недумаю, что они хотели запретить реализациям просто записывать в x.dat[a], y.dat[a], x.dat[b] и y.dat[b], оставляя при этом другие элементы этих структур держа то, что они держали ранее. Вместо того, чтобы пытаться точно определить, какие виды оптимизации должны быть разрешены, они просто предполагали, что реализации будут стремиться наилучшим образом удовлетворить потребности своих клиентов.

...