C указатели и физический адрес - PullRequest
6 голосов
/ 17 февраля 2011

Я только начинаю C. Я читал об указателях в различных книгах / уроках, и я понимаю основы.Но одна вещь, которую я не видел, объяснила, что это за числа.

Например:

int main(){
   int anumber = 10;
   int *apointer;

   apointer = &anumber;

   printf("%i", &apointer);
   }

может возвращать число типа 4231168. Что представляет собой это число?Это какое-то обозначение памяти в ОЗУ?

Ответы [ 11 ]

9 голосов
/ 17 февраля 2011

Много ответов программиста ПК, как всегда.Вот ответ с общей точки зрения программирования.

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

#define MY_REGISTER (*(volatile unsigned char*)0x1234)

Этот код предполагает, что вы знаете, что существует определенный аппаратный регистр, расположенный по адресу 0x1234.Все адреса в компьютере по традиции / для удобства выражены в шестнадцатеричном формате.

В этом примере длина адреса составляет 16 бит, что означает, что шина адреса на используемом компьютере имеет ширину 16 бит.Каждая ячейка памяти в вашем компьютере имеет адрес.Таким образом, на 16-битной адресной шине вы можете иметь максимум 2 ^ 16 = 65536 адресуемых ячеек памяти.Например, на ПК адрес обычно имеет длину 32 бита, что дает вам 4,29 миллиарда адресуемых ячеек памяти, то есть 4,29 гигабайта.

Чтобы подробно объяснить этот макрос:

  • 0x1234это адрес регистра / ячейки памяти.
  • Нам нужно получить доступ к этой ячейке памяти через указатель, поэтому мы ввели целочисленную константу 0x1234 в беззнаковый указатель на символ = указатель на байт.
  • Предполагается, что интересующий нас регистр имеет размер 1 байт.Если бы он был размером в два байта, мы могли бы вместо этого использовать unsigned short.
  • Аппаратные регистры могут обновляться в любое время (их содержимое является «изменчивым»), поэтому программе нельзя разрешать делать какие-либопредположения / оптимизация того, что хранится в них.Программа должна считывать значение из регистра каждый раз, когда регистр используется в коде.Чтобы применить это поведение, мы используем ключевое слово volatile.
  • Наконец, мы хотим получить доступ к регистру так же, как если бы это была простая переменная.Поэтому добавляется *, чтобы взять содержимое указателя.

Теперь программа может получить доступ к определенной ячейке памяти:

MY_REGISTER = 1;
unsigned char var = MY_REGISTER;

Например, такой код используется везде во встроенных приложениях.

(Но, как уже упоминалось в других ответах, вы не можете делать подобные вещи на современных ПК, поскольку они используют так называемую виртуальную адресацию, что дает вам пощечину, если вы попытаетесь это сделать.)

7 голосов
/ 17 февраля 2011

Это адрес или место памяти, на которое ссылается указатель.Однако лучше всего рассматривать это как непрозрачную величину - вас никогда не интересует фактическое значение указателя, а только то, к чему он относится.

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

2 голосов
/ 17 февраля 2011

Это адрес ячейки памяти 1 , в которой хранится ваша переменная. Вам не нужно беспокоиться о точном значении, вы просто должны знать, что разные переменные имеют разные адреса, что «непрерывная память» (например, массивы) имеет смежные адреса, ...

Кстати, чтобы напечатать адрес, сохраненный в указателе, вы должны использовать спецификатор %p в printf.

<ч />
  1. Обратите внимание, что я не сказал «RAM», потому что в большинстве современных ОС «память», которую видит ваш процесс, представляет собой виртуальную память, т. Е. Абстракцию фактической памяти, управляемой ОС.
2 голосов
/ 17 февраля 2011

Это виртуальный адрес переменной anumber.Каждая программа имеет свое собственное пространство памяти, и это пространство памяти отображается на физическую память.Идентификатор отображения, выполняемый процессором, и служебные данные, используемые для этого, поддерживаются операционной системой.Таким образом, ваша программа никогда не знает, где она находится в физической памяти.

1 голос
/ 17 февраля 2011

Многие люди говорили вам, что числовое значение указателя будет обозначать его адрес. Это один способ, которым реализации могут это делать, но очень важно, что стандарт C говорит об указателях:

  • Указатель nil всегда имеет числовое значение 0 при работе на языке программирования C. Однако фактическая память, содержащая указатель, может иметь любое значение, если это специальное, зависящее от архитектуры значение постоянно обрабатывается как ноль, и реализация заботится о том, чтобы это значение воспринималось как 0 исходным кодом на языке C. Это важно знать, поскольку указатели 0 могут отображаться как разные значения на определенных архитектурах при проверке с помощью отладчика памяти низкого уровня.
  • Нет никакого требования, что значения указателя каким-либо образом связаны с реальными адресами. Это могут быть также абстрактные идентификаторы, разрешенные с помощью LUT или аналогичные.
  • Если указатель обращается к массиву, правила арифметики указателя должны выполняться, т.е. int array[128]; int a, b; a = (int)&array[120]; b = (int)&array[100]; a - b == 20 ; array + (a-b) == &array[20]; &array[120] == (int*)a
  • Арифметика указателей между указателями на разные объекты не определена и вызывает неопределенное поведение.
  • Отображение указателя на целое число должно быть обратимым, т. Е. Если число соответствует действительному указателю, преобразование в этот указатель должно быть действительным. Однако арифметика (указатель) числового представления указателей на различные объекты не определена.
0 голосов
/ 31 мая 2013

это не адрес переменной anumber, который печатается, а адрес указателя, который будет напечатан. Посмотрите внимательно. Если бы это был просто «apointer», то мы бы увидели адрес переменной anumber.

0 голосов
/ 17 февраля 2011

Это адрес указателя.

«anumber» занимает некоторое место в оперативной памяти, данные в этом месте содержат число 10.

«apointer» также занимает некоторое место в оперативной памяти, данные в этом месте содержат расположение «anumber» в оперативной памяти.

Итак, скажем, у вас есть 32 байта оперативной памяти, адреса 0..31

Например, позиция 16 у вас есть 4 байта, значение «anumber» 10

Например, в позиции 20 у вас есть 4 байта, значение «apointer» 16, позиция «anumber» в RAM.

То, что вы печатаете, равно 20, позиция указателя в ОЗУ.

Обратите внимание, что на самом деле это не непосредственно в ОЗУ, а в виртуальном адресном пространстве, которое отображается в ОЗУ. Для понимания указателей вы можете полностью игнорировать виртуальное адресное пространство.

0 голосов
/ 17 февраля 2011

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

0 голосов
/ 17 февраля 2011

apointer - это «адрес» переменной anumber.Теоретически, это может быть реальное физическое место в ОЗУ, где хранится значение anumber, но в реальности (в большинстве ОС) это может быть место в виртуальной памяти.Результат тот же, хотя.

0 голосов
/ 17 февраля 2011

в этом случае & apointer представляет адрес в оперативной памяти переменной указателя apointer

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...