char* p = "hello world";
程序员通常会将变量的地址分配给指针。但在上面的例子中,指针指向哪里?
以及世界上的什么
int x =42;
int* p= &x;
int ** r = &p;
答案 0 :(得分:14)
它指向程序的只读存储器中的一个区域(通常在程序的机器代码本身中),其中包含ASCII序列hello world
。将其与:
char p[] = "hello world";
在堆栈上创建一个12 char
的数组,可以像任何其他变量一样修改,并且:
char *p = strdup("hello world");
在堆上创建一个12 char
的数组,并将p
设置为指向堆内存的可读和可写空间的指针。
关于你(完全不相关)的第二个问题:
int** r = &p;
比它看起来更简单,虽然它也很糟糕。 &p
是p的地址。所以如果我们这样做了:
int x;
int *y = &x;
然后指针y
指向变量x
,因此分配给*y
更改x
(反之亦然)。我们可以为任意复杂的类型执行此操作:
int *x;
int **y = &x;
现在y
仍然是指向x
的指针,但x
也是指针。因此,在您的示例中,r
是指向int
的指针,它的值是p
(指向char
的指针)的地址。但是,执行此操作是一个坏主意,因为许多平台都存在从char *
类型转换为更大指针类型的对齐问题。
答案 1 :(得分:3)
字符串常量“hello world”必须位于应用程序的某个位置,并在运行时加载到内存中。通常,这是在可执行文件的数据部分中。指针p指向内存中的该地址。
第二个例子只是取p的地址。鉴于p在堆栈上,它将成为当前堆栈的地址。
答案 2 :(得分:2)
插图可能会有所帮助。鉴于以下声明:
char *s = "hello world";
int x = 45;
int *p = &x;
int **r = &p;
char q[] = "hello world";
假设以下内存映射(地址和布局完全是任意的,并不代表任何真实的架构):
0x00 0x01 0x02 0x03 0x00008000: 'h' 'e' 'l' 'l' 0x00008004: 'o' ' ' 'w' 'o' 0x00008008: 'r' 'l' 'd' 0x00 ... s: 0x01000000: 0x00 0x00 0x80 0x00 x: 0x01000004: 0x00 0x00 0x00 0x2D p: 0x01000008: 0x01 0x00 0x00 0x04 r: 0x0100000C: 0x01 0x00 0x00 0x08 q: 0x01000010: 'h' 'e' 'l' 'l' 0x01000014: 'o' ' ' 'w' 'o' 0x01000018: 'r' 'l' 'd' 0x00
字符串文字“hello world”是具有静态范围的char
(C ++中的const char
)的12元素数组,意味着在程序启动时为其分配内存并保持分配直到程序终止。字符串文字在内存中的确切位置取决于平台,但最好假设内存是不可写的(即,您无法使用strcpy()
或strcat()
或sprintf()
更改其内容等)。语言标准明确指出,尝试修改字符串文字会导致未定义的行为。
该行
char *s = "hello world";
将s
定义为char的指针,使用文字的地址对其进行初始化(本例中为0x00008000)。
该行
int x = 45;
将x
定义为整数,并使用值45(以十六进制表示法绘制)初始化它。
该行
int *p = &x;
将p
定义为指向int的指针,并使用x
(0x01000004)的地址对其进行初始化。
该行
int **r = &p;
将r
定义为指向int的指针,并使用p
(0x01000008)的地址对其进行初始化。
请注意,指针类型是不同的,并不总是兼容。即使s
,p
和r
都解析为此特定假设中的32位地址值,但它们具有不同的类型并且不一定是可互换的,即使它们都设置为指向同一位置。某些平台对不同的指针类型使用不同的大小和表示。
最后,作为一个额外的奖励,我们有一行
char q[] = "hello world";
将q
定义为12个元素的char数组(大小取自用于初始化它的字符串文字的大小),并使用字符串的内容对其进行初始化文字。
答案 3 :(得分:1)
声明指针时使用的星号符号表示它是一个指针(它是其类型复合说明符的一部分),不应与解除引用运算符混淆,也不应与星号混淆。
如果要访问它返回的值,则必须在其前面加上双星号。
答案 4 :(得分:0)
指向以NULL结尾的字符串的第一个字符。 r指向一个指针......也就是说它指向一个将指针保存到整数的位置。
答案 5 :(得分:-1)
p是与"hello world"
一起存储的内存地址,因此内存p'address具有地址位置...
int** r = &p;
所以r是对该地址的引用......有点混乱