|
bool "третье состояние" |
|
|
|
Jul 22 2009, 07:34
|
Участник

Группа: Свой
Сообщений: 54
Регистрация: 25-11-04
Из: Тула
Пользователь №: 1 228

|
Код #include <stdbool.h>
int main() { bool B; B = 13; //B = 1 B = !B; //B = 0 unsigned char* Ptr; Ptr = (unsigned char*)(&B); *Ptr = 13; //B = 13 bool B2; B2 = B; //B2 = 12 B2 = !B; //B2 = 13 return 0; } Почему при присваивание непосредственно числа все нормально ( B = 13 ), а при присваивании другово bool ( B2 = B ) мусор остается? Так и должно быть?
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 14)
|
Jul 22 2009, 08:34
|
Участник

Группа: Свой
Сообщений: 54
Регистрация: 25-11-04
Из: Тула
Пользователь №: 1 228

|
явное преобразование типа тоже не помогает: Код B2 = (bool)(B); //B2 = 12
|
|
|
|
|
Jul 22 2009, 08:38
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Цитата(HEX @ Jul 22 2009, 10:34)  Почему при присваивание непосредственно числа все нормально ( B = 13 ), а при присваивании другово bool ( B2 = B ) мусор остается? Так и должно быть? В каждом компиляторе работа с bool может быть организована по-разному. Ваш компилятор очевидно конверсию в bool производит на этапе присваивания, а работает с bool-переменными, используя только их младший бит. Такой подход эффекитивен при компиляции, т.к. упрощает булевские операции, позволяя делать их "не глядя". В противном случае приведение типа пришлось бы делать при каждой булевской операции с ее использованием. Таким образом "мусор" не мешает работе программы, поскольку все остальные биты, кроме младшего, в работе не участвуют.
|
|
|
|
|
Jul 22 2009, 08:40
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(HEX @ Jul 22 2009, 14:34)  явное преобразование типа тоже не помогает: Код B2 = (bool)(B); //B2 = 12 B2 = (int)( B ) ; ?
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jul 22 2009, 08:56
|
Участник

Группа: Свой
Сообщений: 54
Регистрация: 25-11-04
Из: Тула
Пользователь №: 1 228

|
Цитата(Xenia @ Jul 22 2009, 12:38)  Таким образом "мусор" не мешает работе программы... Если бы не мешали я бы может и не заметил: Код //B = 13 if (B == true) printf("true\n"); else printf("false\n");
B = !B; if (B == true) printf("true\n"); else printf("false\n"); выводит только "true"
|
|
|
|
|
Jul 22 2009, 10:28
|
Участник

Группа: Свой
Сообщений: 54
Регистрация: 25-11-04
Из: Тула
Пользователь №: 1 228

|
я в этом вижу потенциальную проблему, например, при чтении бинарного файла данных.Придется производить доп. операции, что бы избавиться от мусора: Код //data.bin = {0x0D, 0x00, 0x00, 0x00} f = fopen("data.bin", "r"); fread(&B, sizeof(B), 1, f); //B = 13 fclose(f); //Избавляемся от мусора if (B) B = true; else B = false;
|
|
|
|
|
Jul 22 2009, 11:00
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Цитата(HEX @ Jul 22 2009, 11:56)  выводит только "true" Я уже объясняла, что сложности с набитыми мусором булевскими переменными возникают исключительно при проведении булевских операций над ними, что заставляет компилятор во имя эффективности использовать только младший бит этого числа. Однако при проверке булевой переменной (например для ветвления по оператору if) такой проблемы не возникает, и тут компилятор проверяет переменную "честно". Это потому, что поверка одного бита "стоит" ровно столько же, сколько проверка всех битов - тестирование регистра на нулевое значение занимает столько же инструкций, как и тестирование одного его бита. А вот булевские операции (типа ! ~ ^ & |) над одним битом производятся элементарно, а над мусорными переменными нет. Код //B = 13 if (B == true) printf("true\n"); else printf("false\n"); - тут B тестируется на ненулевое значение, а потому ЛЮБОЕ ненулевое значение B напечатает true. Код B = !B; if (B == true) printf("true\n"); else printf("false\n"); - а тут операция B = !B компилируется экономно - инверсией младшего бита. Можно было бы сразу инвертировать все биты числа, но мусор от этого останется мусором, но в false не превратится. Попробуйте сами вместо компилятора оттранслировать B = !B. Тогда поймете, что без ветвления по if/else этого сделать нельзя. Код //Избавляемся от мусора if (B) B = true; else B = false; Избавляться от мусора короче так: B = B ? true : false;
|
|
|
|
|
Jul 22 2009, 11:11
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(HEX @ Jul 22 2009, 13:28)  я в этом вижу потенциальную проблему, например, при чтении бинарного файла данных.Придется производить доп. операции, что бы избавиться от мусора: Естественно придется. Но несколько иначе: Код //data.bin = {0x0D, 0x00, 0x00, 0x00} f = fopen("data.bin", "r"); uint8_t Tmp; fread(&Tmp, sizeof(Tmp), 1, f); B = Tmp; fclose(f); Все. Компилятор знает, как преобразовать внутреннее представление uint8_t во внутреннее представление bool. Не надо мешать ему, пытаясь сделать его работу через неявное преобразование при помощи указателей. А если в вашем компиляторе bool будет 32 бита, что вы считаете из файла вашим методом? Цитата(HEX @ Jul 22 2009, 11:56)  Если бы не мешали я бы может и не заметил: Код //B = 13 if (B == true) printf("true\n"); else printf("false\n"); Еще раз: каким образом вы присвоили B значение 13? Оператором B = 13 вы не можете присвоить переменной типа bool значение, отличное от true и false. Если вы присвоили через указатель на другой тип - это жульничество, и компилятор ведет себя как считает нужным. Ибо запись B = 13 фактически означает B = bool(13), и 13 в B ну никак попасть не сможет.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jul 22 2009, 12:13
|
Частый гость
 
Группа: Свой
Сообщений: 151
Регистрация: 21-02-06
Пользователь №: 14 561

|
Цитата(HEX @ Jul 22 2009, 11:56)  Если бы не мешали я бы может и не заметил: Код //B = 13 if (B == true) printf("true\n"); else printf("false\n");
B = !B; if (B == true) printf("true\n"); else printf("false\n"); выводит только "true" ...посмотрите в дизассемблере код который соответствует этому фрагменту Цитата(HEX @ Jul 22 2009, 10:34)  Код #include <stdbool.h>
int main() { bool B; B = 13; //B = 1 B = !B; //B = 0 unsigned char* Ptr; Ptr = (unsigned char*)(&B); *Ptr = 13; //B = 13 bool B2; B2 = B; //B2 = 12 B2 = !B; //B2 = 13 return 0; } Почему при присваивание непосредственно числа все нормально ( B = 13 ), а при присваивании другово bool ( B2 = B ) мусор остается? Так и должно быть? Так и должно быть, потому что тип bool предполагает использование преопределенных констант для данной реализации компилятора.
|
|
|
|
|
Jul 22 2009, 14:57
|
Участник

Группа: Свой
Сообщений: 54
Регистрация: 25-11-04
Из: Тула
Пользователь №: 1 228

|
Цитата(Сергей Борщ @ Jul 22 2009, 15:11)  А если в вашем компиляторе bool будет 32 бита у меня собственно так и есть, универсальность эта другая тема. Цитата(Сергей Борщ @ Jul 22 2009, 15:11)  Если вы присвоили через указатель на другой тип - это жульничество да жульничество, но интервейс вызова Read(void* Buff, int N) достаточно широко используется, есть и другие варианта попадание мусора в bool. Но проверять значение после подозрительных мест надо обязательно. Потом такой момент, если используется swtich, пусть даже с параметром enum, все равно в голове помним о левых значениях, которые обработаем default. При работе с bool переменными думается true/false, а там может и вигная какая то быть, причем "заразная", передается присваиванием ( B2 = B1 ). А явное преобразование B = (bool)( B ) по моему, должно работать четко.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|