2009-07-10 3 views
8

Для:C указатели Вопрос

int *a; 

a представляет собой адрес, где целое число может быть сохранено. &a - это адрес, в котором хранится a. Затем, где хранится &a? И где хранится &(&a)? А где хранится &(&(&a))? Где останавливается это сохранение адресов?

+1

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

+0

Если вы действительно ищете, как указываются указатели, ознакомьтесь с этим ответом на: http://stackoverflow.com/questions/991075/does-a-pointer-also-have-any-address-or-memory-allocation/991152#991152 –

+0

Здесь также: http://stackoverflow.com/questions/96285/in- ci-can not-grasp-pointers-and-classes/98525 # 98525 –

ответ

4

&a Постоянная ссылка.

&(&a) является незаконным.

+1

константа внутри этой области = P – DevinB

+2

'& a' is not действительно постоянный. Переменная может быть в стеке. Он вычисляется во время выполнения. –

+3

Это rvalue (то есть то, что вы положили на правую сторону оператора присваивания), и, следовательно, постоянный в отношении программы. Тот факт, что он может иметь разные значения для разных прогонов, не имеет значения. –

7

Если вы явно не пишете &a, он не будет храниться нигде. Если вы пишете, тогда адрес будет вычислен и сохранен либо в неназванной переменной (временном), либо в именованной переменной, которую вы пишете.

Например:

functionCall(&a); // address will be in a temporary variable used for passing the parameter 
int** b = &a; // address will be stored in variable b 
otherFunctionCall(&&a); // illegal, since &a is an expression operator & can't be applied to it 
+0

Даже если я не пишу & a, должно быть какое-то место, где фактически хранится? – dharm0us

+0

@dta: Я не уверен, что понимаю ваш вопрос здесь ... 'a' хранится в стеке, как и любая другая локальная переменная. Когда вы пишете '& a', программа вычисляет адрес того, где хранится стек' a' (он уже знает указатель стека, потому что это регистр и он знает смещение в фрейме стека, потому что он скомпилирован как константа) и делает с ней что-то, что объясняется sharptooth. – rmeador

+0

Ну, да. Вы снова путаете переменную и адрес переменной. Они обычно не равны. Переменная - это фрагмент памяти, расположенный на некотором адресе и содержащий некоторое значение. – sharptooth

3

& а есть адрес. Это значение, результат оператора &, примененного к a, и не «сохраняется», и не имеет адреса, поэтому & (& a) недействителен. Это как 2 + 3.

0

a является переменной типа «адрес int»; & a - адрес переменной a; & (& а) будет адрес адреса переменной а, что не имеет смысла

4

a не является «адрес, где целое число может быть сохранено». a - это переменная, достаточно большая, чтобы удерживать адрес целого. Единственное «целое» можно хранить непосредственно в a это адрес целого, рассматривается как само целое:

int *a; 
int b; 

a = &b; 

printf("a is now %x\n", (unsigned int) a); 

Это правильно, что a сам имеет адрес, который &a, но адрес не является хранится где-то явным, во время выполнения.

На участке, вы можете быть в состоянии сохранить то, что выглядит как целое число 0:

a = 0; 

Но это просто сокращенный синтаксис для «указателя NULL», то есть значение указателя гарантированно не быть адресом любого фактического объекта.

+0

Это ответ не идеален ... но это определенно +1, поскольку я думаю, что он определенно получил наилучший шанс объяснить/ответить на исходный вопрос для искателя. – Beska

0

Не совсем. a - это переменная, в которой может храниться адрес некоторого целого. &a - адрес a, i. е. адрес переменной a, который может содержать адрес некоторого целого.

Очень важно: до и до тех пор, пока адрес a не будет адресован, это неинициализированный указатель. Попытка использовать то, на что указывает, приведет к непредсказуемым результатам и, скорее всего, приведет к краху вашей программы.

0

У вас может быть указатель на указатель.

Ex:

void foo(int **blah) 
{ 
int *a = *blah; 

... 
} 

Указатель занимает память. Это всего лишь маленький контейнер, который содержит адрес чего-то. Он просто не может заняться «отсутствием пространства», потому что все на компьютере представлено каким-то образом цифрами. Просто, поскольку C/C++ сконцентрирован, int * a является просто указателем на объект и не занимает места. Это значит, что вам не нужно управлять какой-либо памятью ... он держит машину отдельно от кода.

+0

Указатель, безусловно, занимает память. int * a; выделяет локальную переменную в стеке, которая занимает, однако, для хранения указателя на вашем компьютере требуется много байтов. – Dima

1

Вы можете продолжать идти вечно:

int value = 742; 
int *a = &value; 
void *b = &a; 
void *c = &b; 
void *d = &c; 

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

+0

Да, но использование void обычно нахмурилось. Лучше написать int ** b, int *** c, int **** d и т. Д. – Dima

0

int * a; является указателем на int, называемым 'a'. & a; является различием int * a. это указывает на самого себя. это то, что вы использовали бы, чтобы указать на переменную, которую вы хотели бы передать от функции к функции. derefrence - просто причудливое слово для «получения адреса назад». & (& (& a)) не является допустимым выражением, как указано ранее. вы можете сделать указатель на указатель на указатель. Возможно, это то, о чем вы думаете. В таком случае вы бы отменили последний указатель, и компьютер должен понять, о чем вы говорите.

Чтобы ответить на вопрос «где», «сохранен»; в стеке.

пожалуйста, если я ошибаюсь ни на чем, дайте мне знать.

0

& a - это номер, который является rvalue: вы можете сохранить его где-нибудь, если хотите, в переменной, которую вы объявили или присвоили, типа int *.

А именно:

int a = 42; 
&a; /* this does not store the address of a because you've not assigned the value to a variable */ 
int **aptr = &a; /* aptr is on the stack */ 
int **aptr2 = (int*)malloc(sizeof(int*)); 
aptr2 = &a; /* aptr2 is in the heap */ 

& (& а) не является законным синтаксис. Если вы хотите указатель на указатель на междунар:

int b = 39; 
int *bptr = &b; 
int **ptr2bptr = &bptr; 

Вы должны создать уровни косвенности.

С выше, вы можете это сделать, если вы хотите:

printf("%d\n", *aptr); 
printf("%d\n", *aptr2); 
printf("%d\n", *bptr); 
printf("%d\n", **ptr_to_bptr); 

Производство вывод:

42 
42 
39 
39 
2

int *a переменная размер указателя, так же, как int b бы автоматический int variable.

Если эта декларация в функции, эта переменная автоматически и хранится на [stack] (http://en.wikipedia.org/wiki/Stack_(data_structure)#Hardware_stacks) во время выполнения (простой стек декремента выделяет память для него).

Если декларация носит глобальный характер, то «a» - это просто , отображаемый в исполняемом файле .DATA.

Все больше & признаки прилагаемая может «создать хранилище», из-за временных переменных, которые вы используете для холдем;):

b = &a; //the address in the executable's .DATA or on the stack (if `a` auto) 
c = &b; //the address of `b` on the stack, independent of `a` or `&a` 
d = &c; //the address of `c` on the stack, independent of `a` or `&a` 
z = &(&a); //error: invalid lvalue in unary '&' 

Последняя строка жалуется на то, что & требует операнда должен быть lvalue. То есть, что-то назначаемое - например, b и c. (&a) как результат выражения, которое нигде не хранится, поэтому не является lvalue.

0
int* a; 

Эта строка просто объявляет указатель на целое число. У этого указателя есть ячейка памяти, в которой вы можете получить адрес использования & a. & - оператор , который возвращает адрес того, на что он запущен. Но если вы не присвоите это значение нигде, больше не возможно &.

Что касается вашего вопроса о том, где & a хранится, скорее всего, в регистре. Если вы не используете значение, оно будет немедленно отменено. (И регистры не имеют адресов памяти, поэтому вы не можете сделать & (& a))

1

В основе вашей проблемы, по-видимому, лежит недостаток понимания физической природы памяти и указателей. Не так, как работает код. Как я уверен, вы знаете, что физическая память состоит из большой группы соседних ячеек. Адреса этих ячеек фиксированы и жестко закодированы самим компьютером, а не программными приложениями или используемым вами языком программирования. Когда вы обратитесь к & a, вы имеете в виду физический блок памяти, который в настоящее время хранит ваше значение, которое вы сохранили в башенном компьютере. «a» - это просто имя, которое вы дали компьютеру, чтобы он точно знал, какой блок памяти должен найти значение, которое вы сохранили. Я думаю, что в значительной степени распространяется адрес памяти.
Теперь перейдем к указателям. Указатель - это еще один адрес памяти, на который ссылается компьютер. У него есть любое имя, которое вы ему даете. В этом случае его следует называть чем-то другим, кроме того же имени, которое вы указали на свое первое значение. Позволяет называть его «b». Основываясь на том, как вы это объявили. b может хранить только один тип данных .... другое место памяти .... поэтому, когда я говорю: b = & a Я говорю, что адрес памяти 'b' (который предназначен только для сохранить адреса памяти), заключается в том, чтобы удерживать адрес памяти 'a'. Между тем на другой стороне города адрес памяти «a» имеет целое число, сохраненное в нем.

Надеюсь, что это не запуталось, я постарался не получить здесь всех техно-болтовней. Если ты все еще смущен. Повторите попытку, в следующий раз я объясню код.

-UBcse

1

В C, переменная x может выступать в качестве значения (на правой стороне =, где он называется Rvalue), или он может выступать в качестве контейнера для значения (в левой части =, где это называется lvalue). Вы можете взять адрес x, так как вы можете взять адрес любой lvalue — это дает вам указатель на контейнер. Но поскольку указатель представляет собой rvalue, а не контейнер, вы никогда не сможете взять &(&x). Фактически для любого номера l, &l является законным, но &(&l) никогда не является законным.

Смежные вопросы