指针可以指向自己吗?

Laz*_*zer 39 c pointers

这里提到这个问题.

我的问题是:如果指针变量与其值具有相同的地址,它是否真的指向自身?

例如 - 在下面的代码中,是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);
}
Run Code Online (Sandbox Code Playgroud)

如果a不是指向自身的指针,则同样的问题再次出现:指针可以指向自身吗?
另外,自指向指针有用吗?

小智 38

void* p = &p;
Run Code Online (Sandbox Code Playgroud)

它并不是非常有用,但是指向自身的结构在长度为1的循环列表中很有用:

typedef struct A {
  struct A* next;
} A;

A a = { &a };
Run Code Online (Sandbox Code Playgroud)

根据你的确切例子,我相信你的意思是:

int* a;
int b = (int)&a;
a = (int*)b;

// which can be simplified to:
int* a = (int*)&a;
Run Code Online (Sandbox Code Playgroud)

  • @Phil:它在概念上是不同的,这是所有好处的来源,但请注意A :: next确实指向它自己,因为它是结构的第一个成员,所以`&a ==&a.next`. (3认同)
  • 请注意,您对结构所做的与他试图做的不同。指向自身的指针与具有指向自身的指针的结构完全不同。不过,对于示例来说 +1,因为这可能是他应该考虑使用自引用指针的原因。 (2认同)

Cam*_*Cam 34

你实际上在做什么并没有指针指向自己.您正在使用为指针分配的内存空间来存储指针的位置.指向int的指针指向int - 从不指向int的其他指针,包括它自身.

例如,假设您创建了一个指针a:

int * a;
Run Code Online (Sandbox Code Playgroud)

它在内存中占有一席之地:

   4     a (5)    6
[....][00000000][....]
Run Code Online (Sandbox Code Playgroud)

在这个简单的例子中,假设a位于内存位置'5'.

如果你这样做:

a = (int*)&a;
Run Code Online (Sandbox Code Playgroud)

......会发生以下情况:

   4     a (5)    6
[....][00000005][....]
Run Code Online (Sandbox Code Playgroud)

这里发生的a是指向它认为是位置5的整数.这也恰好&a是指向的内存位置,但是在a指向的内容中,它现在指向位置处的整数5 - 那个整数是5.

例如,这两个都可以工作:

cout<<(int)a;//outputs 5
cout<<*a;//Outputs the integer at memory location 5 - which is 5.
Run Code Online (Sandbox Code Playgroud)

如果你想创建一个指向a的指针,你绝对可以 - 通过以下方式之一:

int **b = (int**)a;
Run Code Online (Sandbox Code Playgroud)

要么

int ** b = &a;
Run Code Online (Sandbox Code Playgroud)



但要意识到这a不是指向自身的指针是非常重要的.它是指向它存储位置整数的指针- 恰好与它自己的位置相同.


为了进一步展示(通过一个更简单的例子)正在发生的事情,类似的事情可能发生在int.也就是说,您可以存储内部的内存位置int:

int a=999;
Run Code Online (Sandbox Code Playgroud)

a 现在在内存中有一个位置,其值为999(我们假装它已被放置在内存位置'46'):

  45     a (46)   47
[....][00000999][....]
Run Code Online (Sandbox Code Playgroud)

它在位置'46' - 如果我们想要,我们可以将这个数字存储为整数a:

a=(int)&a;

  45     a (46)   47
[....][00000046][....]
Run Code Online (Sandbox Code Playgroud)

现在a等于&a值,但不是类型 - a只是一个整数,它现在并不神奇,因为我们用它来存储自己的内存位置.


ast*_*ght 16

内存地址FFFFFFFF可以存储值FFFFFFFF

  • 假设一个32位的地址空间,没有.没有空间在该地址存储4字节值.:) (4认同)

Phi*_*hil 6

好吧,首先我要更改代码:

int **a;
a = (int **)&a;  // otherwise you get a warning, since &a is int ***
Run Code Online (Sandbox Code Playgroud)

我不确定你为什么会这样做,但是这是允许的.

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 **
Run Code Online (Sandbox Code Playgroud)

他们应该打印出同样的东西.

The address of a is 0x7fffe211d078
a holds the address 0x7fffe211d078
The value at 0x7fffe211d078 is 0x7fffe211d078
Run Code Online (Sandbox Code Playgroud)

请注意,这不是一个好主意,因为第一次a = (int **)&a强制a转换是强制持有它不应该持有的值的黑客.你声明它是一个int **但是试着强迫它int ***进入它.从技术上讲,大小是相同的,但通常不这样做,因为人们希望a int *保存可以用作的东西的地址int,等等.