В следующем коде я memset()
stdbool.h
bool
переменную со значением 123
. (Возможно, это неопределенное поведение?) Затем я передаю указатель на эту переменную функции-жертве, которая пытается защитить себя от неожиданных значений с помощью условной операции. Однако GCC почему-то вроде бы вообще убирает условную операцию.
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
void victim(bool* foo)
{
int bar = *foo ? 1 : 0;
printf("%d\n", bar);
}
int main()
{
bool x;
bool *foo = &x;
memset(foo, 123, sizeof(bool));
victim(foo);
return 0;
}
user@host:~$ gcc -Wall -O0 test.c user@host:~$ ./a.out 123
Что особенно раздражает, так это то, что функция victim()
на самом деле находится внутри библиотеки и выйдет из строя, если значение больше 1.
Воспроизводится в версиях GCC 4.8.2-19ubuntu1 и 4.7.2-5. Не воспроизводится на лязгах.
x
какbool
, вы пообещали компилятору, что вы сохраните в нем только0
или1
. Сохраняя123
вx
1, вы солгали компилятору. Если вы солгаете компилятору, он отомстит. - Генри Спенсер - person Keith Thompson   schedule 26.12.2014CHAR_BIT
бит (иCHAR_BIT >= 8
), он также достаточно велик, чтобы содержать значение123
. Вам не запрещается хранить123
в объектеbool
из-за его размера, но это неопределенное поведение. - person Keith Thompson   schedule 26.12.2014<stdbool.h>
, вы можете рассмотреть возможность использования только значенийtrue
иfalse
(как в Pascal с типомBoolean
). Это сделает ваш код более читабельным и избавит вас от других значений. - person Grzegorz Szpetkowski   schedule 27.12.2014true
как битовый шаблон01111011
. Что еще более важно, он может выбрать11111111
в качестве битового шаблона дляtrue
. Преобразованиеtrue
вint
должно давать 1, но это не ограничивает битовый шаблонtrue
. (Сравните: от1.0f
доint
.) - person MSalters   schedule 27.12.2014bool
- это целочисленный тип, и он должен соответствовать тем же правилам, что и другие целочисленные типы.true
- это макрос, определенный в<stdbool.h>
, который расширяется до1
. Если присвоение значения1
объектуbool
устанавливает его битовую комбинацию в11111111
, тогда 7 битов старшего разряда должны быть битами заполнения. (И все нулевые биты должны быть представлением для0
, но не обязательно единственным представлением.) - person Keith Thompson   schedule 27.12.20140111101
перед битом значения1
? И в основном комментарий, на который я ответил, предполагал, что эти биты обязательно должны быть равны нулю, что я считаю особенно неверным. - person MSalters   schedule 27.12.2014_Bool
сговорились, чтобы запутать вещи способами, которые мне пока лень исследовать. Итог: следует избегать хранения значений, отличных от0
и1
, в объекте_Bool
. - person Keith Thompson   schedule 27.12.2014