我的问题是:如果指针变量与其值具有相同的地址,它是否真的指向自身?
例如 - 在下面的一段代码中,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
不是指向自身的指针,那么同样的问题再次出现:指针可以指向自身吗?
另外,自指向指针有用吗?
答案 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*
会为您提供int
,int*
的值类型)。对于指向指针的变量,其值类型必须为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;
它指向自身。