присвоение NULL указателям x64 - PullRequest
0 голосов
/ 26 марта 2012

У меня есть процесс, который работает нормально на платформах x86.
Теперь я скомпилировал его для x64, и вдруг я не могу присвоить NULL своим указателям.
Если я сделаю что-то вроде этого:

void* pointy = NULL;

Это будет указывать на 0x0000000100000000
Что происходит?

Ответы [ 2 ]

2 голосов
/ 26 марта 2012

При выполнении программы, содержащей:

void* pointy = NULL;

он инициализирует объект указателя pointy, поэтому он содержит значение нулевой указатель (при условии, что у вас есть #include d один из заголовков, который определяет макрос NULL).

A пустой указатель - это значение данного типа указателя, которое отличается от любого другого значения этого типа. По логике это указатель, который ни на что не указывает.

Нулевой указатель может быть представлен в исходном коде C ++ с помощью константы нулевого указателя . NULL - это макрос, который расширяется до константы нулевого указателя. Литерал 0 также является константой нулевого указателя, как и ключевое слово nullptr (недавнее дополнение к языку). Это не обязательно означает, что значение нулевого указателя представляется как ноль со всеми битами, но обычно это так, и я хотел бы поспорить, что оно есть в вашей системе.

Если вы напечатаете значение pointy:

std::cout << "pointy = " << pointy << "\n";

вы увидите заданное реализацией представление нулевого указателя. В моей системе это печатает pointy = 0. В других системах это может быть 0x0, или [null], или почти что-нибудь еще, но он должен распознаваться как нулевой указатель.

Чтобы проверить, является ли значение pointy нулевым указателем, сравните его в вашей программе:

if (pointy == NULL) {
    std::cout << "Yes, it's a null pointer\n");
}
else {
    std::cout << "No, it's not a null pointer (?)\n");
}

Обратите внимание, что вы не можете разыменовать pointy, чтобы определить, на что он указывает, потому что он имеет тип void*. Если бы это был какой-то другой тип указателя, например int*, то вы могли бы написать код для разыменования его, но поведение этого кода было бы неопределенным; наиболее вероятным поведением будет сбой программы, но все возможно.

Что касается того, что вы видите в своем отладчике, я не могу догадаться без дополнительной информации. Возможно, ваш отладчик работает неправильно, но это маловероятно. Возможно, вы смотрите на то, на что указывает pointy (вероятно, на адрес памяти 0), но это также маловероятно; поскольку указатель void* не указывает на данные какого-либо указанного типа, отладчик не может их отобразить.

Может быть, вы установили точку останова для определения pointy и смотрите на значение, сохраненное в нем, когда вы достигнете точки останова? Если это так, возможно, вы просто видите значение до инициализации. Попробуйте шагнуть вперед на одну строчку и снова посмотреть на значение. Если на x86 это работало корректно, возможно, это связано с тем, что мусор, который содержался в pointy до его инициализации, выглядел как нулевой указатель.

В любом случае язык C ++ ничего не говорит о том, что вы увидите при использовании отладчика; он только определяет поведение программы во время ее выполнения. Если у вас возникли проблемы с использованием вашего отладчика, это законный вопрос, но вам нужно сказать нам, какой отладчик вы используете, что именно вы делаете с ним, и показать нам небольшую полную программу, которая показывает проблему .

РЕДАКТИРОВАТЬ: В комментарии к другому ответу вы написали

Я хочу, чтобы "pointy" указывал на 0.

Есть по крайней мере две очень разные вещи, которые могут означать.

Это:

int* ptr = new int(0);

заставляет ptr указывать на объект где-то в памяти; этот объект содержит значение int 0. Можно сказать, что «ptr указывает на 0», но было бы точнее сказать, что «ptr указывает на объект, значение которого равно 0».

Это:

int *nptr = 0;

делает значение nptr равным нулевому указателю . Это, вероятно, то, что вы подразумеваете под «указывает на 0», но лучше сказать, что значение nptr является нулевым указателем. (Если вы рассматриваете nptr как адрес машинного уровня, вполне вероятно, что он содержит нулевой адрес ячейки памяти; другими словами, nptr указывает на ячейку памяти 0. Но в терминах C ++ это на самом деле не указывает в любую ячейку памяти вообще; значение нулевого указателя - это специальное адресоподобное значение, используемое для различения указателей, которые нигде не указывают, от указателей, указывающих на объекты.)

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

void* pointy = NULL;  // or 0, or nullptr

- это абсолютно правильный способ сделать это.

2 голосов
/ 26 марта 2012

Нуль не обязательно битовый ноль. Его значение определяется реализацией.


То есть это все одно и то же:

void* pointy = NULL;
void* pointy = 0;
void* pointy = nullptr;

Они присваивают значение нулевого указателя на pointy. То, что это значение на уровне битов, совершенно не определено, и не обязательно все биты ноль!

Если ваш код таков, как вы говорите, то либо: ваша платформа действительно использует это значение для нуля, это не так, и ваш компилятор сломан, или нет, и вы неправильно читаете значение.

В любом случае код C ++ в порядке и устанавливает pointy в ноль. Больше не нужно ни о чем беспокоиться.

...