Я имею инструмент распространения DNS разработанный для ответа на подобные вопросы.
Источник выпущен под AGPLv3.
(Да, интерфейс является довольно основным в данный момент:))
Вы могли также узнать серверы имен для домена с командой "хоста":
[davidp@supernova:~]$ host -t ns stackoverflow.com stackoverflow.com name server ns51.domaincontrol.com. stackoverflow.com name server ns52.domaincontrol.com.
Адреса памяти не должны интерпретироваться таким образом как целые числа со знаком. Знак числа зависит от наивысшего набора бит (при условии представления в виде дополнения до двух, которое используется подавляющим большинством систем, используемых в настоящее время), поэтому адрес памяти выше 0x80000000 в 32-битной системе будет отрицательным, а память адрес ниже 0x80000000 будет положительным. В этом нет никакого реального значения.
Вы должны печатать адреса памяти, используя модификатор % p
; в качестве альтернативы некоторые люди используют % 08x
для печати адресов памяти (или % 016llx
в 64-битных системах). Это всегда будет распечатываться как целое число без знака в шестнадцатеричном формате, что гораздо полезнее, чем десятичное целое число со знаком.
int a;
printf("%p\n", &a);
Чтобы максимально соответствовать стандарту, передайте "% 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.
Вы должны передать средство форматирования указателя:
printf("%p\n",foo);
Вы распечатываете в десятичном формате. Вероятно, вы захотите распечатать расположение памяти в шестнадцатеричном формате (используя "% p") (большинство адресов памяти по соглашению показаны в шестнадцатеричном формате).
Также указатель не имеет знака, но при преобразовании в целое число со знаком он может быть положительным или отрицательным.
Между прочим, передача указателя на printf
с переменной формата, предназначенной для печати целого числа, вызывает неопределенное поведение. Вы всегда должны явно приводить к правильному типу, чтобы получить неуказанное или определяемое реализацией поведение (в зависимости от приведения).
Указатели не являются целыми числами со знаком, они больше похожи на целые числа без знака. Однако вы распечатываете их, как если бы они были целыми числами со знаком. В 32-битной системе есть несколько вещей, которые могут иметь длину 32 бита: int
, unsigned int
, float
и указатели. В общем, вы не можете определить, какие это, просто взглянув на них, но все они означают разные вещи. (В качестве эксперимента вы можете передавать различные целые числа и печатать их как числа с плавающей запятой, и наоборот: в целом это плохая практика, но она может показать вам, что разные типы данных означают разные вещи.)
Функции, которые принимают переменное количество значений аргументы («вариативные» функции) делают это сложным образом. В частности, они не проверяют типы аргументов. Вы можете передавать любые аргументы printf ()
и другим подобным функциям, но ваша проблема - добиться их согласования со спецификатором формата. Это означает, что функция не имеет возможности получить правильный тип (как если бы вы передали float
в функцию вроде int foo (int)
).
Передача неправильные типы аргументов приводят к неопределенному поведению и, в частности, могут привести к проблемам, если вы передадите аргументы неправильного размера. В большинстве 64-битных систем указатели являются 64-битными, а int
- 32.
Следовательно, вам нужно использовать правильную вещь в строке формата. printf ("% p", & a);
распечатает адрес a
в виде указателя, что вам и нужно. Стандарт требует что-то вроде printf ("% p",
Вы также можете использовать printf ("% p", & a)
. % p
- это спецификатор формата указателя для вывода значения указателя способом, определяемым реализацией. На практике это почти то же самое, что и% x, но будет обрабатывать случай, когда указатель больше, чем int.
printf - это не какой-то волшебный инструмент интерпретации. Все, что он делает, если вы зададите ему "% d", показывает вам, как битовый шаблон, содержащийся в этой переменной, выглядит как целое число.
Что касается того, почему некоторые указатели являются отрицательными, а некоторые положительными, все это означает, что некоторые имеют установлен старший бит, а некоторые нет. Какие адреса присваиваются объектам, на самом деле является делом вашей операционной системы (обычно с некоторой аппаратной помощью). Язык программирования не имеет права голоса.
На вашем месте я бы не распечатал адреса таким образом. Если вы действительно чувствуете необходимость взглянуть на них, используйте «% x» вместо «% d». Это напечатает их в шестнадцатеричном формате, что значительно упростит определение того, какие биты включены, а какие нет.
Помимо использования % p
, вы также можете привести к uintptr_t
, чтобы убедиться, что unisgned integer.
Используйте PRIuPTR
(или PRIXPTR
для шестнадцатеричного) вида
, чтобы получить правильный спецификатор формата:
printf("%" PRIuPTR "\n", (uintptr_t)(void *)&foo);