Используйте объединение и 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
Примечание: Этот ответ относится к языку 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.
Похоже, что некоторые люди неправильно понимают, в чем разница между NULL, '\ 0' и 0. Итак, чтобы объяснить и в попытке избежать повторения сказанного ранее:
Постоянное выражение типа int со значением 0 или выражение этого типа, приведенное к типу void *, является константой нулевого указателя , который при преобразовании в указатель становится нулевым указателем . Стандарт гарантирует, что сравнение не равно любому указателю на любой объект или функцию .
NULL - это макрос, определенный в константе нулевого указателя .
'\ 0' - это конструкция, используемая для представления нулевого символа , используемого для завершения строки.
Нулевой символ - это байт, все биты которого установлены в 0.
Если 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'
.
Все три определяют значение нуля в разном контексте.
Они три всегда разные, когда вы смотрите на память:
NULL - 0x00000000 or 0x00000000'00000000 (32 vs 64 bit)
NUL - 0x00 or 0x0000 (ascii vs 2byte unicode)
'0' - 0x20
Надеюсь, это проясняет ситуацию.
NUL с одним L, завершает строку.
NULL с двумя буквами L ни на что не указывает.
И я поставлю золотого быка.
Что не существует трех-L NULLL.
«NUL» не равно 0, а относится к символу NUL ASCII. По крайней мере, я видел, как это использовали. Нулевой указатель часто определяется как 0, но это зависит от среды, в которой вы работаете, и от спецификации той операционной системы или языка, которые вы используете.
В ANSI C нулевой указатель определяется как целочисленное значение 0 . Таким образом, любой мир, в котором это неправда, не соответствует требованиям ANSI C.
Байт со значением 0x00 в таблице ASCII является специальным символом, называемым «NUL» или «NULL». В C, поскольку вы не должны встраивать управляющие символы в исходный код, они представлены в строках C с экранированным 0, т. Е. «\ 0».
Но истинный NULL - это , а не ценность. Это отсутствие ценности. Для указателя это означает, что указателю не на что указывать. В базе данных это означает, что в поле нет значения (что не то же самое, что сказать, что поле пустое, 0 или заполнено пробелами).
Фактическое значение для данной системы или формат файла базы данных, используемый для представления NULL, не обязательно 0x00.
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
В чем разница между 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 ++.