c指针

时间:2017-09-26 09:18:43

标签: c arrays string pointers memory-address

在下面的代码中,str是一个存储数组Goodbye地址的指针。数组Goodbye的地址从4196004开始,指针*str2的值为-1226226648。我的问题是,有没有办法使用指针Goodbye打印数组*str2的地址?

我尝试使用printf("%d %d %s\n", *str2, str2, str2);取消引用str2,然后打印71,这是H的ascii,但我如何打印地址4196004 < / p>

int main(int argc, char **argv) {

char str1[] = "Hello";
char *str2 = "Goodbye";

printf("%d %d %s\n", &str1, str1, str1);
printf("%p %d %s\n", &str2, str2, str2);

}

Output: 
-1226226640 -1226226640 Hello
-1226226648 4196004 Goodbye

4 个答案:

答案 0 :(得分:1)

您的代码调用未定义的行为,因为您尝试不使用%p

打印地址

printf()提及:

  

p指针地址

并且不要像你应该的那样投降到void

所以,改为这样做:

printf("%p %p %s\n", (void*)&str1, (void*)str1, str1);
printf("%p %p %s\n", (void*)&str2, (void*)str2, str2);

可能的输出:

0x7ffddaf7e67a 0x7ffddaf7e67a Hello
0x7ffddaf7e670 0x4005c4 Goodbye

答案 1 :(得分:0)

关于str2,我们可以区分“指针str2指向的地址”,这是字符串文字Goodbye将驻留的地址(例如0x10007bf04) “存储指针str2的地址”,其是存储地址值0x7fff5fbff710的变量(例如0x10007bf04)的地址。

int main(int argc, char **argv) {

    char str1[] = "Hello";
    char *str2 = "Goodbye";

    printf("%p %p %s\n", (void*)&str1[0], (void*)str1, str1);
    printf("%p %p %s\n", (void*)&str2, (void*)str2, str2);

}

与指针相反,*str2表示字符值,因为它取消引用指针str2。获取“* str2的地址”将是str2指向的字符串文字的第一个字符的地址。您可以将其写为&(*str2)&str2[0],但都会转换为str2

请注意,使用格式"%d"打印指针会调用未定义的行为。

答案 2 :(得分:0)

首先修复未定义的行为 - 将指针投射到void*,然后使用%p打印它们:

printf("%p %p %s\n", (void*)&str1, (void*)str1, str1);
printf("%p %p %s\n", (void*)&str2, (void*)str2, str2);

produces the following output

0x7ffe95676bf0 0x7ffe95676bf0 Hello
0x7ffe95676be8 0x2b4dca5eb7d4 Goodbye

让我们看看为什么str1str2的打印行之间存在差异。

原因是str1是一个数组,而str2是一个指针。当您使用运算符&获取指向数组的指针时,会生成指向数组初始元素的指针;当您将数组隐式转换为指针时,您还会获得指向数组初始元素的指针。因此,%p&str1的{​​{1}}打印输出的str1值相同。

另一方面,0x7ffe95676bf0是一个指针。它指向某个东西(字符串文字str2),但它也有自己的地址。当您在没有"Goodbye"的情况下打印str2时,您会获得指针的值,即字符串文字&的位置。但是,当您打印"Goodbye"时,会得到指针&str2的指针,指针是str2的位置。这与str2的位置不同,因此打印输出不同。

如果您从地址"Goodbye"开始,即

str2

您可以通过解除引用来获取char *str2 = "Goodbye"; char **ptrStr2 = &str2; 的位置,即

"Goodbye"

Demo.

答案 3 :(得分:0)

对于初学者,您应在函数printf中使用正确的转换说明符。否则,函数的行为是未定义的。

所以这些电话

printf("%d %d %s\n", &str1, str1, str1);
printf("%p %d %s\n", &str2, str2, str2);

是错误的,因为转换说明符%d使用了指针。

  

我的问题是,有没有办法打印数组Goodbye的地址使用   指针* str2?

实际上,对应于字符串文字"Goodbye"的数组地址与字符串文字的第一个字符的地址相同。

char *str2 = "Goodbye";

但是,您无法使用指针str2获取指向字符串文字的指针。

有什么问题?

指针str2不知道它是指向类型为char的单个对象还是指向某个数组的第一个字符。它没有保留这样的信息。

考虑到与字符串文字"Goodbye"对应的数组的类型为char[8]。因此,指向数组的指针应具有类型char ( * )[8]

你可以写例如

char ( *str2 )[8] = &"Goodbye";

在这种情况下,指针str2确实将具有数组的地址。否则,在示例中定义指针

char *str2 = "Goodbye";

你无法获得数组的地址,因为正如提到的那样,指针对数组及其大小一无所知。

另一方面,字符串文字的第一个字符的地址值等于指向字符串文字的指针的值。那就是考虑第一个声明

char str1[] = "Hello";

然后表达式str1&str1将产生相同的值,尽管表达式具有不同的类型。第一个类型为char *(如果在数组指示符被隐式转换为指向其第一个元素的指针时在上下文中使用该表达式)。第二个类型为char ( * )[6]。但这两个值都是相同的。:)

从输出中可以看出(假设您使用了正确的转换说明符)

-1226226640 -1226226640 Hello