адрес памяти положительная или отрицательная величина в c?

Я имею инструмент распространения DNS разработанный для ответа на подобные вопросы.

Источник выпущен под AGPLv3.

(Да, интерфейс является довольно основным в данный момент:))

Вы могли также узнать серверы имен для домена с командой "хоста":

[davidp@supernova:~]$ host -t ns stackoverflow.com
stackoverflow.com name server ns51.domaincontrol.com.
stackoverflow.com name server ns52.domaincontrol.com.

7
задан Bob Kaufman 11 March 2010 в 14:03
поделиться

10 ответов

Адреса памяти не должны интерпретироваться таким образом как целые числа со знаком. Знак числа зависит от наивысшего набора бит (при условии представления в виде дополнения до двух, которое используется подавляющим большинством систем, используемых в настоящее время), поэтому адрес памяти выше 0x80000000 в 32-битной системе будет отрицательным, а память адрес ниже 0x80000000 будет положительным. В этом нет никакого реального значения.

Вы должны печатать адреса памяти, используя модификатор % p ; в качестве альтернативы некоторые люди используют % 08x для печати адресов памяти (или % 016llx в 64-битных системах). Это всегда будет распечатываться как целое число без знака в шестнадцатеричном формате, что гораздо полезнее, чем десятичное целое число со знаком.

int a;
printf("%p\n", &a);
29
ответ дан 6 December 2019 в 04:49
поделиться

Чтобы максимально соответствовать стандарту, передайте "% p" в строке формата в printf () и приведите аргумент в void * .

printf("%p\n", (void*)&a);
printf("%p\n", (void*)foo);

Цитата из проекта стандарта (n1401.pdf)

    7.20.6.1 The fprintf function

8   The conversion specifiers and their meanings are:

p       The argument shall be a pointer to void. The value of the pointer
        is converted to a sequence of printing characters, in an
        implementation-defined manner.
7
ответ дан 6 December 2019 в 04:49
поделиться

Вы должны передать средство форматирования указателя:

printf("%p\n",foo);
6
ответ дан 6 December 2019 в 04:49
поделиться

Вы распечатываете в десятичном формате. Вероятно, вы захотите распечатать расположение памяти в шестнадцатеричном формате (используя "% p") (большинство адресов памяти по соглашению показаны в шестнадцатеричном формате).

4
ответ дан 6 December 2019 в 04:49
поделиться

Также указатель не имеет знака, но при преобразовании в целое число со знаком он может быть положительным или отрицательным.

Между прочим, передача указателя на printf с переменной формата, предназначенной для печати целого числа, вызывает неопределенное поведение. Вы всегда должны явно приводить к правильному типу, чтобы получить неуказанное или определяемое реализацией поведение (в зависимости от приведения).

3
ответ дан 6 December 2019 в 04:49
поделиться

Указатели не являются целыми числами со знаком, они больше похожи на целые числа без знака. Однако вы распечатываете их, как если бы они были целыми числами со знаком. В 32-битной системе есть несколько вещей, которые могут иметь длину 32 бита: int , unsigned int , float и указатели. В общем, вы не можете определить, какие это, просто взглянув на них, но все они означают разные вещи. (В качестве эксперимента вы можете передавать различные целые числа и печатать их как числа с плавающей запятой, и наоборот: в целом это плохая практика, но она может показать вам, что разные типы данных означают разные вещи.)

Функции, которые принимают переменное количество значений аргументы («вариативные» функции) делают это сложным образом. В частности, они не проверяют типы аргументов. Вы можете передавать любые аргументы printf () и другим подобным функциям, но ваша проблема - добиться их согласования со спецификатором формата. Это означает, что функция не имеет возможности получить правильный тип (как если бы вы передали float в функцию вроде int foo (int) ).

Передача неправильные типы аргументов приводят к неопределенному поведению и, в частности, могут привести к проблемам, если вы передадите аргументы неправильного размера. В большинстве 64-битных систем указатели являются 64-битными, а int - 32.

Следовательно, вам нужно использовать правильную вещь в строке формата. printf ("% p", & a); распечатает адрес a в виде указателя, что вам и нужно. Стандарт требует что-то вроде printf ("% p",

3
ответ дан 6 December 2019 в 04:49
поделиться

Вы также можете использовать printf ("% p", & a) . % p - это спецификатор формата указателя для вывода значения указателя способом, определяемым реализацией. На практике это почти то же самое, что и% x, но будет обрабатывать случай, когда указатель больше, чем int.

1
ответ дан 6 December 2019 в 04:49
поделиться

printf - это не какой-то волшебный инструмент интерпретации. Все, что он делает, если вы зададите ему "% d", показывает вам, как битовый шаблон, содержащийся в этой переменной, выглядит как целое число.

Что касается того, почему некоторые указатели являются отрицательными, а некоторые положительными, все это означает, что некоторые имеют установлен старший бит, а некоторые нет. Какие адреса присваиваются объектам, на самом деле является делом вашей операционной системы (обычно с некоторой аппаратной помощью). Язык программирования не имеет права голоса.

На вашем месте я бы не распечатал адреса таким образом. Если вы действительно чувствуете необходимость взглянуть на них, используйте «% x» вместо «% d». Это напечатает их в шестнадцатеричном формате, что значительно упростит определение того, какие биты включены, а какие нет.

0
ответ дан 6 December 2019 в 04:49
поделиться

Используйте следующий код:

printf("%u",&a);
-1
ответ дан 6 December 2019 в 04:49
поделиться

Помимо использования % p , вы также можете привести к uintptr_t , чтобы убедиться, что unisgned integer.

Используйте PRIuPTR (или PRIXPTR для шестнадцатеричного) вида , чтобы получить правильный спецификатор формата:

printf("%" PRIuPTR "\n", (uintptr_t)(void *)&foo);
0
ответ дан 6 December 2019 в 04:49
поделиться
Другие вопросы по тегам:

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