这个指针做了什么?

时间:2009-11-04 07:11:11

标签: c

char* p = "hello world";

程序员通常会将变量的地址分配给指针。但在上面的例子中,指针指向哪里?

以及世界上的什么

int x =42;
int* p= &x;
int ** r = &p;

6 个答案:

答案 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)的地址对其进行初始化。

请注意,指针类型是不同的,并不总是兼容。即使spr都解析为此特定假设中的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是对该地址的引用......有点混乱