我试图更好地理解指针。我有这段代码:
char theString[MAX] = "All your base are belong to us";
char *i = theString;
char *j = theString;
printf("%p\n", &theString);
printf("%p\n", &i);
printf("%p\n", &j);
运行程序时,我总是得到三个单独的地址。我知道每次编译时内存地址都会改变,并且不是静态的。但是,由于我已将i和j设置为“ theString”中第一个字符的地址,因此我认为它们将是相同的地址吗?
非常感谢您的帮助。
答案 0 :(得分:2)
运行程序时,我总是得到三个单独的地址。
您打印了三种不同内容的地址:i
,j
和theString
。如果打印i
和j
的值,您会发现它们都指向theString
。 &
运算符自己获取变量i
和j
本身的地址。
以下是修改您的打印语句以同时显示变量的方法:
printf("With &:%p\tWithout &:%p\n", &theString, theString);
printf("With &:%p\tWithout &:%p\n", &i, i);
printf("With &:%p\tWithout &:%p\n", &j, j);
输出为:
With &:0x7ffeefbfee20 Without &:0x7ffeefbfee20
With &:0x7ffeefbfee08 Without &:0x7ffeefbfee20
With &:0x7ffeefbfee00 Without &:0x7ffeefbfee20
这表明您有三个不同的指针变量,它们都指向同一内存位置。
答案 1 :(得分:1)
&j
和&i
是指针的地址,而不是它们引用的对象
printf("%p\n", (void *)i);
printf("%p\n", (void *)&j);
与int a = 3;
和int b = 3;
相同,您不会期望&a
与&b
相同
答案 2 :(得分:0)
尝试一下:
printf("Address of theString = %p, value of theString = %s\n", (void *) theString, theString);
printf("Address of i = %p, value of i = %p\n", (void *) &i, (void *) i );
printf("Address of j = %p, value of j = %p\n", (void *) &j, (void *) j );
theString
,i
和j
在内存中都是独立的对象,因此它们都将具有不同的地址。 i
和j
将具有相同的 value ,即theString
的地址。
一些注意事项:
除非它是sizeof
或一元&
运算符的操作数,或者是用于初始化声明中的字符数组的字符串文字,即 expression 类型为“ T
的N元素数组的em>将被转换(“衰变”)为类型为“指向T
的指针”的表达式,该表达式的值将为第一个元素。因此,在第一个printf
语句中,不需要&
运算符即可获取theString
的地址。表达式theString
和&theString
都将求值为数组第一个元素的地址,但是表达式的类型将不同(char *
与char (*)[MAX]
)。
%p
转换说明符期望其对应的参数具有类型void *
。这是C语言中需要显式将指针表达式转换为void *
的地方。
i
和j
的类型为char *
,因此表达式 &i
和{{1}的类型}是&j
。
编辑
我接受了您的声明,并通过我自己的内存转储实用程序运行了它们:
char **
这是输出:
#include "dumper.h"
#define MAX 32
int main( void )
{
char theString[MAX+1] = "All your base are belong to us";
char *i = theString;
char *j = theString;
char *names[] = {"theString", "i", "j" };
void *addrs[] = {theString, &i, &j};
size_t sizes[] = { sizeof theString, sizeof i, sizeof j };
dumper( names, addrs, sizes, 3, stdout );
return 0;
}
x86是低位字节序,因此需要从右到左,从下到上读取多字节值。您会看到 Item Address 00 01 02 03
---- ------- -- -- -- --
theString 0x7ffee727fa90 41 6c 6c 20 All.
0x7ffee727fa94 79 6f 75 72 your
0x7ffee727fa98 20 62 61 73 .bas
0x7ffee727fa9c 65 20 61 72 e.ar
0x7ffee727faa0 65 20 62 65 e.be
0x7ffee727faa4 6c 6f 6e 67 long
0x7ffee727faa8 20 74 6f 20 .to.
0x7ffee727faac 75 73 00 00 us..
0x7ffee727fab0 00 00 00 00 ....
i 0x7ffee727fa20 90 fa 27 e7 ..'.
0x7ffee727fa24 fe 7f 00 00 ....
j 0x7ffee727fa18 90 fa 27 e7 ..'.
0x7ffee727fa1c fe 7f 00 00 ....
和i
包含相同的 value (j
),它是0x7ffee727fa90
的第一个元素的地址。
答案 3 :(得分:0)
i and j are char pointers , nothing but variables in short and like every variable they have their own locations and hence, their own addresses.
These variables hold the address of theString and hence both point to the same address
When you print &i and &j , it prints out the address of i and j in memory and hence, you get different addresses. But they hold the address of the same variable
Your code prints out the address of the array theString , pointer i address and pointer j address.
char theString[MAX] = "All your base are belong to us";
char *i = theString;
char *j = theString;
printf("%p\n", &theString);
printf("%p\n", &i);
printf("%p\n", &j);
答案 4 :(得分:0)
关于:
printf("%p\n", &theString);
在C语言中,引用数组的名称会降级为数组第一个字节的地址,因此无需使用“ address of”运算符。编译器会抱怨:
: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘char (*)[##]’ [-Wformat=]
其中“ ##”是数组中元素的数量
答案 5 :(得分:0)
请注意,i和j指向拥有自己内存的theString。 这就是为什么它们具有不同的价值。 但是i,j和theString的值将指向字符数组。
printf("%p\n", theString);
printf("%p\n", i);
printf("%p\n", j);
输出:
0x8efeefbfee50
0x8efeefbfee50
0x8efeefbfee50