2016-08-25 3 views
8

Я начал изучать C (так, вы знаете .. указатели).Значение указателя в C

У меня есть этот код:

#include <stdio.h> 
#include <string.h> 

int main (int argc, char* argv[]) 
{ 
    char c = 'c'; 
    char* cptr = &c; 

    printf("c = %c\n", c); 
    printf("*cptr = %c\n", *cptr); 
    printf("c address = %p\n", &c); 
} 

Мой результат:

c = c 
*cptr = c 
c address = 0x7fff0217096f 

Когда я преобразовать шестнадцатеричное выше десятичной, я получаю: 140720994002157

Мои вопросы:

1) Указывает ли это десятичное значение на адрес памяти? Разве он не слишком велик?

2) Как напечатать значение указателя (что означает адрес переменной c) как десятичное?

+6

Почему вы считаете, что значение указателя является «слишком большой»? – EOF

+0

@EOF Ну, 140720994002157 бит равен примерно 1750 ГБ, правда? – padawanTony

+9

Это виртуальный адрес и не отражает объем оперативной памяти на вашем компьютере. –

ответ

7

Не [адрес] слишком большой?

Это виртуальный адрес, что означает, что его числовое значение необязательно представляет собой порядковый номер байта в физической памяти. Более того, разные процессы могут хранить разные данные на одном виртуальном адресе, поскольку каждый из них имеет свое индивидуальное адресное пространство.

Как напечатать значение указателя в целочисленном формате?

Используйте uintptr_t представлять указатель как целое значение, а затем распечатать, используя PRIuPTR макрос:

#include <stdio.h> 
#include <inttypes.h> 

int main(void) { 
    char c = 'x'; 
    char *p = &c; 
    uintptr_t x = (uintptr_t)p; 
    printf("Pointer as decimal: %"PRIuPTR"\n", x); 
    return 0; 
} 

Demo.

+0

Спасибо. +1 для использования соответствующих ссылок и демонстрации. Об этом, однако, «Это виртуальный адрес, означающий, что его числовое значение не обязательно представляет собой последовательное число байта в физической памяти». У меня возникает соблазн спросить, как я могу напечатать последовательное количество байтов в физической памяти? – padawanTony

+2

@padawanTony Вы не можете, отображение из виртуальной в физическую память в недоступном для пользователя. –

+1

@padawanTony Это что-то скрытое от вашей программы комбинацией операционной системы и аппаратного обеспечения, на котором она запущена, поэтому нет никакого независимого от ОС способа получения сопоставления определенного адреса на физический адрес. Физические адреса также бессмысленны вне контекста диспетчера виртуальной памяти ОС, поскольку страницы (блоки распределения) не имеют особого порядка. – dasblinkenlight

2

1). Вы должны напечатать адрес как printf("c address = %p\n", &c);. Теперь вы пытаетесь распечатать адрес, в котором хранится сама переменная-указатель, что, вероятно, не имеет большого смысла.

Это, как говорится, все еще может быть действительным адресом, предполагающим 64-разрядные адреса.

2). Вы должны будете безопасно преобразовать его в целое число, которое гарантированно будет достаточно большим, чтобы содержать указатель адрес:

#include <inttypes.h> 

printf("c address = %" PRIuPTR "\n", (uintptr_t)&c); 
+0

1) Это именно то, что я делаю 2) Да, это дает правильный результат (это 140723639717279), но 140723639717279 равны примерно 1750 ГБ, верно? У меня, конечно, не так много памяти! Что происходит? – padawanTony

+0

@padawanTony, как сказано выше, это [виртуальная память] (https: //en.wikipedia.org/wiki/Virtual_memory), а не реальный физический адрес. Реализации x86_64 могут использовать [канонический адрес] (https://en.wikipedia.org/wiki/X86-64#Canonical_form_addresses), который исходит из двух концов –

+0

@Luu, но зачем ему использовать виртуальный адрес, если у меня достаточно ОЗУ? – padawanTony