Мой вопрос: Если переменная указателя имеет тот же адрес как свое значение, это действительно указывает на себя?
Например - в следующей части кода, a
указатель на себя?
#include<stdio.h>
int main(){
int* a;
int b = (int)&a;
a = b;
printf("address of a = %d\n", &a);
printf(" value of a = %d\n", a);
}
Если a
не указатель на себя, затем тот же вопрос позирует снова: указатель может указать на себя?
Кроме того, как сам указывающий полезный указатель?
То, что вы на самом деле делаете, не , когда указатель указывает на себя. Вы используете пространство памяти, выделенное для указателя, для хранения местоположения указателя . Указатель на int указывает на целые числа, а не на другие указатели на целые числа, включая самого себя.
Например, предположим, что вы создали указатель a
:
int * a;
Он получает свое собственное место в памяти:
4 a (5) 6
[....][00000000][....]
В этом простом примере предположим, что a находится в ячейке памяти «5».
Если бы вы сделали это:
a = (int*)&a;
... произошло бы следующее:
4 a (5) 6
[....][00000005][....]
Здесь происходит то, что
указывает на то, что, по его мнению, является целым числом в позиции 5. Это также оказывается той же ячейкой памяти, на которую указывает & a
, но в контексте того, на что указывает a
, теперь он указывает на целое число в позиции 5 - и это целое число равно 5.
Например, оба из них будут работать:
cout<<(int)a;//outputs 5
cout<<*a;//Outputs the integer at memory location 5 - which is 5.
Если вы хотите создать указатель на a, вы определенно сможете - любым из этих способов:
int **b = (int**)a;
или
int ** b = &a;
Но очень важно понимать что
не является указателем на самого себя. Это указатель на целое число в том месте, где он хранит - которое просто совпадает с его собственным местоположением.
Чтобы еще больше показать (на еще более простом примере), что происходит дальше нечто подобное может произойти с int
.То есть вы можете сохранить в себе место в памяти int
:
int a=999;
a
теперь имеет место в памяти и имеет значение 999 (мы представим, что оно было помещено в ячейка памяти «46»):
45 a (46) 47
[....][00000999][....]
Она находится в ячейке «46» - если бы мы хотели, мы могли бы сохранить это число как целое в пределах a
:
a=(int)&a;
45 a (46) 47
[....][00000046][....]
, а теперь a
равно & a
по значению, но не по типу - a
является просто целым числом, теперь оно не указывает на себя волшебным образом только потому, что мы использовал его для хранения собственной ячейки памяти.
void* p = &p;
Это не очень полезно, но структуры, указывающие на самих себя, полезны в круговых списках длиной 1:
typedef struct A {
struct A* next;
} A;
A a = { &a };
В вашем точном примере, я полагаю, вы имели в виду:
int* a;
int b = (int)&a;
a = (int*)b;
// which can be simplified to:
int* a = (int*)&a;
Разыменование указателя приводит к значению его типа значения (например, разыменование int *
дает вам int
, тип значения int *
s). Чтобы переменная указывала на указатель, ее тип значения должен быть int *
, что не относится к int *
, как было указано ранее. Итак, чтобы указатель указывал на себя, нужно было бы выполнить какое-то преобразование, чтобы получить его компилятором:
int* a;
a = reinterpret_cast<int*>(&a);
Для разыменования a
тогда у вас будет int
, значение которого совпадает с адресом, по которому находится a
(усечение по модулю адреса для соответствия типу), но это по-прежнему int
, а не int *
, что потребует еще одного приведения.
Указатель на указатель часто называют дескриптором , который имеет другой тип ( int **
), чем указатель ( int *
) . (Обратите внимание, что дескриптор int **
имеет тип значения int *
.)
Да и нет, потому что тип указателя почти так же важен, как и значение указателя.
Да, указатель может содержать позицию указателя на самого себя; даже long может содержать позицию указателя на себя. (Инты обычно могут, но я не знаю, везде ли это гарантировано.)
Однако не существует типа, представляющего эти отношения. Если у вас есть указатель, указывающий на самого себя, при разыменовании у вас фактически будет другой тип. Итак:
void *p = &p;
// *p is illegal, even though you probably wanted it to equal 'p'
if( *p != p ) {
printf("Something's wrong");
}
int *i = (int*)&i;
// The following statement is still illegal
if( *i == i ) {
printf("The universe works!");
}
Я бы сказал, что ответ - «нет», потому что это не сработает, если вы не собираетесь злоупотреблять системой типов. Я думаю, это признак того, что вы делаете что-то не так (хотя иногда это, безусловно, необходимо).
Да, можно указывать на себя.
int* a;
a = &a;
Но не иметь никакого применения, по крайней мере, явно, как это.
Ну, сначала я бы изменил код примерно так:
int **a;
a = (int **)&a; // otherwise you get a warning, since &a is int ***
Я не уверен, зачем вы это делаете, но это разрешено.
printf("The address of a is %p\n", &a);
printf("a holds the address %p\n", a);
printf("The value at %p is %p\n", a, *a); // the *a is why we made a an int **
Они должны распечатать то же самое.
The address of a is 0x7fffe211d078
a holds the address 0x7fffe211d078
The value at 0x7fffe211d078 is 0x7fffe211d078
Обратите внимание, что это не очень хорошая идея, поскольку самое первое приведение a = (int **) & a
- это попытка заставить a
хранить значение, которого не должно быть. не держу. Вы объявляете его int **
, но пытаетесь принудительно вставить в него int ***
. Технически размеры одинаковы, но в целом этого не делают, потому что люди ожидают, что int *
содержит адрес чего-то, что можно использовать как int
и т. Д. .
Адрес памяти в FFFFFFFF
может хранить значение FFFFFFFF