Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.58/19: Рейтинг темы: голосов - 19, средняя оценка - 4.58
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
1

[C/C++]Компилятор g++.Странности с true и false.Кто нибудь может прокомментировать/повторить это у себя?

12.10.2009, 00:31. Показов 3769. Ответов 26
Метки нет (Все метки)

Заметил такую странность:
Это проходит компиляцию
C++
1
bool *b = false;
А это нет
C++
1
bool *b = true;
Код
error: cannot convert ‘bool’ to ‘bool*’ in initialization
Компилятор g++.Почему это вообще проходит компиляцию в каком либо виде?Я понимаю,это как-то связано с инициализацией указателя,а false типа трактуется как NULL?Хотелось бы знать,как точно это работает.
У меня случайно сначала так вышло,но вообще подразумевалось
C++
1
bool *b = new bool(false);
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
12.10.2009, 00:31
Ответы с готовыми решениями:

БОМБА это кто нибудь может объяснить?
Взгляните на статичтику http://www.liveinternet.ru/stat/ru/searches.html Гугля обогнал рамблер...

Кто-нибудь может объяснить как это работает?
Именно создание списка не понятно main :: IO() main = do let fib = 0 : 1 : n <-...

может кто нибудь объяснить что это за цифры
дана программа может кто нибудь объяснить что это за цифры s:5:3 program proga7; uses crt; var...

действительно трудная задача может быть кто нибудь рискнет за это взяться
действительно трудная и стоящая задача но может быть кто нибудь рискнет за это взяться если кто...

26
124 / 122 / 0
Регистрация: 30.03.2009
Сообщений: 766
12.10.2009, 00:36 2
потому что у тебя false == 0

получается, что
C++
1
bool *b = false;
эквивалентоно
C++
1
bool *b = 0;
эквивалентно
C++
1
bool *b = NULL;
что допустимо

а вот
C++
1
bool *b = true;
может быть эквивалентно, например,
C++
1
bool *b = 1;
указатель можно сделать null, но присваивать ему в лоб адрес - нехорошо
1
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
12.10.2009, 00:38  [ТС] 3
По идее false и NULL это не одно и тоже.Да и в C++ null не определён вроде,вот и спрашиваю.В-общем,мне как-то видится это нештатной ситуацией
0
124 / 122 / 0
Регистрация: 30.03.2009
Сообщений: 766
12.10.2009, 00:46 4
ну приводится же int к bool всегда, и все к этому привыкли уже, так почему бы и обратно не приводилось?
1
14 / 14 / 4
Регистрация: 08.10.2009
Сообщений: 114
12.10.2009, 01:18 5
Если ты указателю присваиваешь значение 0 (a это и есть false), то это означает, что он не указывает ни на какую область памяти и это нормально. Но если ты хочешь присвоить указателю значение 1 (true), тоесть ты хочешь, чтобы он указывал на область памяти которая начинается с ячейки №1, то ты должен написать так:
C++
1
bool *string = (bool*)true;
1
Evg
Эксперт CАвтор FAQ
21204 / 8220 / 633
Регистрация: 30.03.2009
Сообщений: 22,537
Записей в блоге: 30
11.12.2009, 11:42 6
Цитата Сообщение от Sich_Taras Посмотреть сообщение
Если ты указателю присваиваешь значение 0 (a это и есть false), то это означает, что он не указывает ни на какую область памяти и это нормально. Но если ты хочешь присвоить указателю значение 1 (true), тоесть ты хочешь, чтобы он указывал на область памяти которая начинается с ячейки №1, то ты должен написать так:
Немного не так. По стандарту Си должно быть некоторое специальное значение указателя и чтобы ни один объект не мог иметь такой адрес. В заголовочных файлах такое значение должно быть описано как NULL. Если p - это некий указатель, то "if (p)" должно трактоваться как "if (p != NULL)". При этом стандарт не говорит, чему должен быть равен NULL. Для большинства "нормальных" систем NULL равен нулю. Но для некоторых процессоров это может быть не так. На сигнальных процессорах зачастую 0 является валидным адресом. Поэтому в качестве NULL может быть взято значение -1. У сигнальных процессоров мало памяти, а потому адрес 0xffff... как правило находится за рамками физической памяти процессора и поэтому удовлетворяет стандарту (т.е. не существует переменной или функции, адрес которой равен -1)

Когда-то #pragma искал примеры непереносимых кодов. Можно привести ещё пример. Предполагаем, что во всех трёх случаях делается сравнение с NULL

C
1
2
3
4
int *p;
if (p) ....         /* переносимый */
if (p!=NULL) ....   /* переносимый */
if (p!=0) ....      /* НЕ переносимый */
Ну и, соответственно, целочисленное значение, соответствующее NULL, можно присваивать в указатель любого типа без явного преобразования. В нашем случае NULL соотвествует нулю, а потому присваивание false отработало корректно. На вышеупомянутом сигнальном процессоре здесь так же произошла бы ошибка
3
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
11.12.2009, 15:39  [ТС] 7
>Немного не так. По стандарту Си должно быть некоторое специальное значение указателя и чтобы ни один объект не мог иметь такой адрес. В заголовочных файлах такое значение должно быть описано как NULL. Если p - это некий указатель, то "if (p)" должно трактоваться как "if (p != NULL)".

Точно. NULL не равен нулю(не всегда). По идее NULL должен (или нет?) быть определён как
C
1
#define NULL   (void *)0
Чтобы никуда не указывать.
Но я вроде читывал,что в некоторых реализациях компиляторов этим могли пренебречь (особенно в новых) и определить NULL как
C
1
#define NULL  0
0
Evg
Эксперт CАвтор FAQ
21204 / 8220 / 633
Регистрация: 30.03.2009
Сообщений: 22,537
Записей в блоге: 30
11.12.2009, 15:47 8
> Чтобы никуда не указывать

Формулировка неправильная. Просто из всего диапазона адресов выбирается некоторое значение и говорится, что у нас не существует ни одного объекта с таким адресом. Далее заводится макрос NULL с этим значением, а так же на это значение настраивается компилятор, чтобы адэкватно строить сравнения и не выдавать ошибки там где не надо.

Конкретное значение для NULL - зависит от платформы. Т.е. для всех "нормальных" платформ в качестве NULL выбирается ноль (и под такое значение настраивается макрос и компилятор). Для сигнальных процессоров выбирается другое значение.
1
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
11.12.2009, 15:49  [ТС] 9
Да,спасибо,я прочитал внимательнее твой пост
0
Evg
Эксперт CАвтор FAQ
21204 / 8220 / 633
Регистрация: 30.03.2009
Сообщений: 22,537
Записей в блоге: 30
11.12.2009, 15:51 10
Собственно макрос NULL придумали опять-таки по соображениям переносимости кода между платформами. Т.е. программист пишет код:

C
1
2
3
4
5
6
p = NULL;
...
if (p)
{
...
}
Но при этом на одной платформе NULL раскроется в (void*)0, а "if (p)" в "if (p != 0)". Но на другой платформе это может раскрыться в "p = (void*)-1" и "if (p != -1)", но это спрятано на уровне интерфейса и программных соглашений на архитектуру, которые учитывает компилятор. Т.е. указанный выше код будет правильно работать независимо от того, как всё это безобразие настроено
1
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
11.12.2009, 16:17  [ТС] 11
А ты на Багзилле в gcc зарегистрирован? Может,стоит написать им,чтобы компилятор хотя бы предупреждение выводил?
0
Evg
Эксперт CАвтор FAQ
21204 / 8220 / 633
Регистрация: 30.03.2009
Сообщений: 22,537
Записей в блоге: 30
11.12.2009, 16:22 12
g++ всё делает согласно стандарту. Значение false эквивалентно нулю (что эквивалентно NULL), а потому такое присваивание можно делать без явного преобразования типа. А вот для true уже нельзя. Borland C++ работает ровно так же
1
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
04.11.2010, 23:20  [ТС] 13
Evg, я тут кое что накопал про NULL и 0. Выдержка из книги "Beej Guide to Network Programming"
If you set the fields in your struct timeval to 0, select() will timeout
immediately, effectively polling all the file descriptors in your sets. If you set the parameter timeout to
NULL, it will never timeout, and will wait until the first file descriptor is ready. Finally, if you don't care
about waiting for a certain set, you can just set it to NULL in the call to select().
То есть тут подчёркивается,что 0 и NULL - это не эквивалентные значения.
0
В астрале
Эксперт С++
8035 / 4792 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
04.11.2010, 23:25 14
#pragma, В Си действительно различны (ну как и говорил Evg, от архитектуры зависит).
В С++ его не рекомендуется использовать. Но определен он как #define NULL 0. Хотя не исключаю, что тоже может зависить от архитектуры
1
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
04.11.2010, 23:30  [ТС] 15
Хз,от чего это зависит,но select()-довольно часто используемая функция в linux.
про
C
1
#define NULL (void *)0
вроде уже писали.
Мне интересно,как они эти параметры сравнивают внутри select ..
0
Evg
Эксперт CАвтор FAQ
21204 / 8220 / 633
Регистрация: 30.03.2009
Сообщений: 22,537
Записей в блоге: 30
04.11.2010, 23:58 16
Про select. Там не то, о чём ты пишешь. Про ноль говорится, что если ПОЛЯ структуры забить нулями. А про NULL - если вместо указателя на заполненную структуру подсунуть NULL
1
Эксперт С++
3207 / 1734 / 435
Регистрация: 03.05.2010
Сообщений: 3,867
05.11.2010, 00:52 17
Цитата Сообщение от #pragma Посмотреть сообщение
Заметил такую странность:
Это проходит компиляцию
C++
1
bool *b = false;
Согласно синтаксису C++, указателю можно присваивать либо адрес, либо нулевую константу. Никаких NULLов не предусмотрено. Правда, для особых фанатов Страуструп в своей книге пишет: «Гарантируется, что нет объектов с нулевым адресом. Следовательно, указатель, равный нулю, можно интерпретировать как указатель, который ни на что не ссылается.
В языке С было очень популярно определять макрос NULL для представления такого нулевого указателя. Так как в С++ типы проверяются более жестко, использование банального нуля вместо NULL приведет к меньшим проблемам. Если вы чувствуете, что просто обязаны определить NULL, воспользуйтесь
const int NULL = 0;
Модификатор const (§ 5.4) предотвращает ненамеренное замещение NULL и гарантирует, что NULL можно использовать везде, где требуется константа.» <Конец цитаты>
Ну а приведенное вами выражение не одного вас удивило. В книге «Дизайн и эволюция языка C++» Страуструп пишет: «Но меня по-прежнему удивляет правило, согласно которому результат вычисления любого константного выражения, равный 0, принимается в качестве нулевого указателя. Согласно этому правилу, 2-2 и ~-1 - нулевые указатели.» <Конец цитаты>
Видимо поэтому в новом стандарте предусмотрено специальное ключевое слово для обозначения пустого указателя.
0
57 / 57 / 5
Регистрация: 31.10.2010
Сообщений: 103
05.11.2010, 02:27 18
В С++ NULL == 0 и компиляторов C++ для микропроцессоров не существует. Для Си есть, но там NULL хоть что-то значит. Однако в свежем стандарте С++, который готовится, будет таки специальная штука null, которая будет служить как раз для тех же целей что и NULL в Си.
0
В астрале
Эксперт С++
8035 / 4792 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
05.11.2010, 02:28 19
KpeHDeJIb, nullptr, а не null.
0
Эксперт С++
3207 / 1734 / 435
Регистрация: 03.05.2010
Сообщений: 3,867
05.11.2010, 03:05 20
Цитата Сообщение от KpeHDeJIb Посмотреть сообщение
В С++ NULL == 0
В стандарте этого нет. Там только сказано, что значение этого макроса зависит от реализации.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.11.2010, 03:05

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Кто объяснит почему true == false ?
Спасайте! а то я щас повешусь от взрыва мозга! Кто объяснит вот что это за фигня. Когда я в...

Если bool name=false, то !name это true?
Добрый день! Привожу код, взятый из книги. Непонятны следующие строки bool found_one = false;...

Кто-нибудь может подробно объяснить, что такое allocators, зачем это и что с ними делать? Нигде не нашёл инфы
Заранее спасибо.

Что это? .MainFormOnTaskbar := True; Тут ошибка False не помог
begin Application.Initialize; Application.MainFormOnTaskbar := True; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.