Каково различие между ПУСТЫМ УКАЗАТЕЛЕМ, '\0' и 0

Используйте объединение и bitset:

#include <iostream>
#include <bitset>

int main()
{
    union
    {
         float input;   // assumes sizeof(float) == sizeof(int)
         int   output;
    }    data;

    data.input = 2.25125;

    std::bitset<sizeof(float) * CHAR_BIT>   bits(data.output);


    std::cout << bits << std::endl;

    // or

    std::cout << "BIT 4: " << bits[4] << std::endl;
    std::cout << "BIT 7: " << bits[7] << std::endl;
}

Это не может быть массив, но можно получить доступ к битам с [] оператор, как будто Вы использовали массив.

Вывод

$ ./bits
01000000000100000001010001111011
BIT 4: 1
BIT 7: 0
285
задан too honest for this site 13 November 2016 в 22:42
поделиться

9 ответов

Примечание: Этот ответ относится к языку C, а не к C ++.


Нулевые указатели

Целочисленный литерал константы 0 имеет разные значения в зависимости от контекст, в котором он используется. Во всех случаях это по-прежнему целочисленная константа со значением 0 , просто она описывается по-разному.

Если указатель сравнивается с константным литералом 0 , тогда это проверка, является ли указатель нулевым указателем. Этот 0 затем упоминается как константа нулевого указателя. Стандарт C определяет, что 0 , приведенный к типу void * , является как нулевым указателем, так и константой нулевого указателя.

Кроме того, для облегчения чтения макрос NULL предоставляется в файле заголовка stddef.h . В зависимости от вашего компилятора может быть возможно #undef NULL и переопределить его на что-нибудь дурацкое.

Таким образом, вот несколько правильных способов проверки нулевого указателя:

if (pointer == NULL)

NULL равно определен для сравнения, равный нулевому указателю. Реализация определяет фактическое определение NULL , если это действительная константа нулевого указателя.

if (pointer == 0)

0 - другое представление константы нулевого указателя.

if (!pointer)

Это Оператор if неявно проверяет «не равно 0», поэтому мы меняем это значение на «равно 0».

Ниже приведены НЕВЕРНЫЕ способы проверки нулевого указателя:

int mynull = 0;
<some code>
if (pointer == mynull)

Для компилятора это не проверка на нулевой указатель, но проверка на равенство двух переменных. Этот может работать, если mynull никогда не изменяется в коде и константа оптимизации компилятора складывает 0 в оператор if, но это не гарантируется, и компилятор должен выдать хотя бы одно диагностическое сообщение (предупреждение или ошибку). согласно Стандарту C.

Обратите внимание на то, что в языке C это нулевой указатель. Это не имеет значения для базовой архитектуры. Если базовая архитектура имеет значение нулевого указателя, определенное как адрес 0xDEADBEEF, то компилятор должен разобраться с этим беспорядком.

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

if (!pointer)
if (pointer == NULL)
if (pointer == 0)

Ниже приведены НЕПРАВИЛЬНЫЕ способы проверки нулевого указателя:

#define MYNULL (void *) 0xDEADBEEF
if (pointer == MYNULL)
if (pointer == 0xDEADBEEF)

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

Пустые символы

'\ 0' определяется как нулевой символ - это символ, все биты которого установлены в ноль. Это не имеет ничего общего с указателями. Однако вы можете увидеть нечто похожее на этот код:

if (!*string_pointer)

проверяет, указывает ли строковый указатель на нулевой символ

if (*string_pointer)

проверяет, указывает ли строковый указатель на ненулевой символ

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

Кроме того, '\ 0' является (как и все символьные литералы) целочисленной константой, в данном случае с нулевым значением. Итак '\ 0' См. этот pdf для получения информации о стандарте C. См. Разделы 6.3.2.3 Указатели, параграф 3.

333
ответ дан 23 November 2019 в 01:50
поделиться

Похоже, что некоторые люди неправильно понимают, в чем разница между NULL, '\ 0' и 0. Итак, чтобы объяснить и в попытке избежать повторения сказанного ранее:

Постоянное выражение типа int со значением 0 или выражение этого типа, приведенное к типу void *, является константой нулевого указателя , который при преобразовании в указатель становится нулевым указателем . Стандарт гарантирует, что сравнение не равно любому указателю на любой объект или функцию .

NULL - это макрос, определенный в константе нулевого указателя .

'\ 0' - это конструкция, используемая для представления нулевого символа , используемого для завершения строки.

Нулевой символ - это байт, все биты которого установлены в 0.

33
ответ дан 23 November 2019 в 01:50
поделиться

Если NULL и 0 эквивалентны константам нулевого указателя, что я должен использовать? в списке часто задаваемых вопросов C также решает эту проблему:

Программисты на C должны понимать, что NULL и 0 взаимозаменяемы в контексты указателя, и это некастированный 0 вполне приемлемо. Любое использование NULL (в отличие от 0 ) должен быть считается нежным напоминанием о том, что указатель задействован; программисты не должен зависеть от этого (ни для их собственное понимание или компилятора) для различения указателя 0 из целого числа 0 .

Только в контекстах указателя NULL и 0 эквивалентны. NULL должен не может использоваться, если используется другой вид 0 требуется, даже если это может работать, потому что это неправильно стилистическое послание. (Кроме того, ANSI позволяет определение NULL быть ((void *) 0) , который не будет работать на все в контекстах без указателей.) в частности, не используйте NULL , когда Нулевой символ ASCII ( NUL ) является желательным. При необходимости дайте собственное определение

#define NUL '\0'

.

6
ответ дан 23 November 2019 в 01:50
поделиться

Все три определяют значение нуля в разном контексте.

  • контекст указателя - используется NULL и означает, что значение указателя равно 0, независимо от того, 32-битный он или 64-битный (один случай 4 байта остальные 8 байтов нулей).
  • контекст строки - символ, представляющий цифру ноль, имеет шестнадцатеричное значение 0x30, тогда как символ NUL имеет шестнадцатеричное значение 0x00 (используется для завершения строк).

Они три всегда разные, когда вы смотрите на память:

NULL - 0x00000000 or 0x00000000'00000000 (32 vs 64 bit)
NUL - 0x00 or 0x0000 (ascii vs 2byte unicode)
'0' - 0x20

Надеюсь, это проясняет ситуацию.

13
ответ дан 23 November 2019 в 01:50
поделиться

NUL с одним L, завершает строку.

NULL с двумя буквами L ни на что не указывает.

И я поставлю золотого быка.

Что не существует трех-L NULLL.

Что делать с NUL?

4
ответ дан 23 November 2019 в 01:50
поделиться

«NUL» не равно 0, а относится к символу NUL ASCII. По крайней мере, я видел, как это использовали. Нулевой указатель часто определяется как 0, но это зависит от среды, в которой вы работаете, и от спецификации той операционной системы или языка, которые вы используете.

В ANSI C нулевой указатель определяется как целочисленное значение 0 . Таким образом, любой мир, в котором это неправда, не соответствует требованиям ANSI C.

2
ответ дан 23 November 2019 в 01:50
поделиться

Байт со значением 0x00 в таблице ASCII является специальным символом, называемым «NUL» или «NULL». В C, поскольку вы не должны встраивать управляющие символы в исходный код, они представлены в строках C с экранированным 0, т. Е. «\ 0».

Но истинный NULL - это , а не ценность. Это отсутствие ценности. Для указателя это означает, что указателю не на что указывать. В базе данных это означает, что в поле нет значения (что не то же самое, что сказать, что поле пустое, 0 или заполнено пробелами).

Фактическое значение для данной системы или формат файла базы данных, используемый для представления NULL, не обязательно 0x00.

0
ответ дан 23 November 2019 в 01:50
поделиться

NULL не гарантируется равным 0 - его точное значение зависит от архитектуры. Большинство основных архитектур определяют его как (void *) 0 .

'\ 0' всегда будет равен 0, потому что именно так байт 0 кодируется в символьном литерале.

I не помню, должны ли компиляторы C использовать ASCII - в противном случае '0' не всегда может равняться 48. Тем не менее, маловероятно, что вы когда-нибудь встретите систему, которая использует альтернативный набор символов, например EBCDIC, если вы не работаете с очень непонятными системами.

Размеры различных типов будут отличаться в 64-битных системах, но целочисленные значения будут одинаковыми.


Некоторые комментаторы выразили свое мнение сомневаюсь, что NULL равно 0, но не равно нулю. Вот пример программы, вместе с ожидаемым выводом в такой системе:

#include <stdio.h>

int main () {
    size_t ii;
    int *ptr = NULL;
    unsigned long *null_value = (unsigned long *)&ptr;
    if (NULL == 0) {
        printf ("NULL == 0\n"); }
    printf ("NULL = 0x");
    for (ii = 0; ii < sizeof (ptr); ii++) {
        printf ("%02X", null_value[ii]); }
    printf ("\n");
    return 0;
}

Эта программа могла бы напечатать:

NULL == 0
NULL = 0x00000001
0
ответ дан 23 November 2019 в 01:50
поделиться

В чем разница между NULL, '\ 0' и 0

"нулевой символ (NUL)" проще всего исключить. '\ 0' - символьный литерал. В C он реализован как int , поэтому он такой же, как 0, который имеет значение INT_TYPE_SIZE . В C ++ символьный литерал реализован как char , что составляет 1 байт. Обычно это отличается от NULL или 0 .

Затем NULL - это значение указателя, которое указывает, что переменная не указывает на какое-либо адресное пространство. Если оставить в стороне тот факт, что он обычно реализуется в виде нулей, он должен иметь возможность выражать полное адресное пространство архитектуры. Таким образом, в 32-битной архитектуре NULL (скорее всего) составляет 4 байта, а в 64-битной архитектуре - 8 байтов. Это зависит от реализации C.

Наконец, литерал 0 имеет тип int , который имеет размер INT_TYPE_SIZE . Значение по умолчанию INT_TYPE_SIZE может отличаться в зависимости от архитектуры.

Apple пишет:

64-битная модель данных, используемая Mac OS X, известна как «LP64». Это общая модель данных, используемая другими 64-битными системами UNIX от Sun и SGI, а также 64-битным Linux. Модель данных LP64 определяет примитивные типы следующим образом:

  • целые 32-битные
  • длинные-64-битные
  • длинные-длинные также 64-битные
  • указатели 64-битные

Википедия 64-разрядная версия :

Компилятор Microsoft VC ++ использует модель LLP64.

64-bit data models
Data model short int long  long long pointers Sample operating systems
LLP64      16    32  32    64        64       Microsoft Win64 (X64/IA64)
LP64       16    32  64    64        64       Most Unix and Unix-like systems (Solaris, Linux, etc.)
ILP64      16    64  64    64        64       HAL
SILP64     64    64  64    64        64       ?

Изменить : Добавлено больше о символьном литерале.

#include <stdio.h>

int main(void) {
    printf("%d", sizeof('\0'));
    return 0;
}

Приведенный выше код возвращает 4 для gcc и 1 для g ++.

5
ответ дан 23 November 2019 в 01:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: