_Bool тип и строгое алиасинг - PullRequest
       74

_Bool тип и строгое алиасинг

0 голосов
/ 04 сентября 2018

Я пытался написать несколько макросов для безопасного использования типа _Bool, а затем стресс-тестировать мой код. Для злых целей тестирования я придумал этот грязный хак:

_Bool b=0;
*(unsigned char*)&b = 42;

Учитывая, что _Bool составляет 1 байт в реализации sizeof(_Bool)==1), я не вижу, как этот хак нарушает стандарт Си. Это не должно быть строгое нарушение псевдонимов.

Тем не менее, при запуске этой программы через различные компиляторы у меня возникают проблемы:

#include <stdio.h>

int main(void)
{
  _Static_assert(sizeof(_Bool)==1, "_Bool is not 1 byte");

  _Bool b=0;
  *(unsigned char*)&b = 42;
  printf("%d ", b);
  printf("%d", b!=0 );

  return 0;
}

(Код основан на printf неявном повышении аргумента по умолчанию до int)

Некоторые версии gcc и clang выдают 42 42, другие - 0 0. Даже с отключенной оптимизацией. Я бы ожидал 42 1.

Казалось бы, компиляторы предполагают, что _Bool может быть только 1 или 0, но в то же время он счастливо печатает 42 в первом случае.

Q1: Почему это? Содержит ли приведенный выше код неопределенное поведение?

Q2: Насколько надежен sizeof(_Bool)? C17 6.5.3.4 вообще не упоминает _Bool.

1 Ответ

0 голосов
/ 04 сентября 2018

Q1: Почему это? Содержит ли приведенный выше код неопределенное поведение?

Да, это так. Магазин действителен, но впоследствии читается, что как _Bool это не так.

6.2.6 Представления типов

6.2.6.1 Общие сведения

5 Определенные представления объекта не обязательно должны представлять значение типа объекта. Если сохраненное значение объекта имеет такое представление и читается выражением lvalue, которое не имеет символьного типа, поведение не определено. [...]

Q2: Насколько надежен sizeof(_Bool)? C17 6.5.3.4 вообще не упоминает _Bool.

Он надежно сообщит вам количество байтов, необходимое для хранения одного _Bool. 6.5.3.4 также не упоминает int, но вы не спрашиваете, является ли sizeof(int) надежным, а вы?

...