指针可以指向自己吗?

时间:2010-03-28 06:32:34

标签: 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);
}

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

9 个答案:

答案 0 :(得分:37)

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;

答案 1 :(得分:33)

你实际在做的是让指针指向自身。您使用为指针分配的内存空间来存储指针的位置。指向int的指针指向int - 从不指向int的其他指针,包括它自己。

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

int * a;

它在记忆中占有一席之地:

   4     a (5)    6
[....][00000000][....]

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

如果你这样做:

a = (int*)&a;

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

   4     a (5)    6
[....][00000005][....]

这里发生的事情是a指向它认为是位置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;



但是要意识到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只是一个整数,它不指向自身神奇地现在只是因为我们用它来存储自己的内存位置。

答案 2 :(得分:16)

FFFFFFFF的内存地址可以存储值FFFFFFFF

答案 3 :(得分:6)

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

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的东西的地址,依此类推。

答案 4 :(得分:3)

是和否,因为指针的类型几乎与指针的值一样重要。

是的,指针可以包含指向自身的指针的位置;即使很长也可以包含指向自身的指针的位置。 (Ints通常可以,但我不知道这是否在任何地方得到保证。)

但是,没有类型来表示这种关系。如果你有一个指向自身的指针,当你取消引用它时,你实际上有一个不同的类型。所以:

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!");
}

我会说答案是“不”,因为除非你要滥用类型系统,否则它将无效。我认为这表明你做错了什么(虽然有时肯定是必要的)。

答案 5 :(得分:3)

取消引用指针会产生其值类型的值(例如,取消引用int*会为您提供intint*的值类型)。对于指向指针的变量,其值类型必须为int*,而前面所述的int*则不是这种情况。因此,对于指向自身的指针,必须进行某种转换才能通过编译器获取它:

int* a;
a = reinterpret_cast<int*>(&a);

要取消引用a,那么你会得到一个int,其值恰好是a所在的地址(mod截断地址以适应该类型),但它仍然是int而不是int*,这需要另一个演员。

指向指针的指针通常称为句柄,它与指针(int**)的类型不同(int*)。 (请注意,int**句柄的值类型为int*。)

答案 6 :(得分:1)

是的,指针可以指向答案中提到的自身。

一个可能的用例是我们可以使用这个技巧代替NULL指针。您可以初始化int * p =(int *)&amp; p,稍后再检查以查看指针是否有效。如果在我们想要0x0并且整个地址范围是有效地址的系统中,可以使用它。

你也可以在特殊的C程序中使用这个技巧,这些程序在NULL指针使用时不会崩溃,因为你会完全避免它们,并且在解除引用系统时不会崩溃。它会导致错误的行为,但在某些情况下可能有助于调试。

答案 7 :(得分:0)

是的,有可能指向自己。

int* a;
a = &a;

但没有任何用处,至少明确是这样的。

答案 8 :(得分:0)

只是:

int *a = (int*)&a;
cout<<"checking: \n"<<&a<<"\n"<<a;

它指向自身。