c指针指向的数组的打印地址

问题描述:

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

我想,解引用str2此行printf("%d %d %s\n", *str2, str2, str2);和它打印71这是ASCII码为H,但我怎么会打印地址4196004

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 
+1

你有不确定的行为。请参阅https://stackoverflow.com/q/5286451/4389800 – usr

+2

@artic sol在您的代码片段中没有名称str。:) –

你的代码调用未定义行为,因为您尝试打印地址,而不使用%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 

关于str2我们可以区分“地址到指针str2点”,这是地址,其中字符串文字Goodbye将从“存储指针str2的地址”(其为变量的地址(例如0x7fff5fbff710))驻留(例如0x10007bf04)其中存储地址值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"打印指针会调用未定义的行为。

开始通过固定未定义行为 - 投你的指针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是一个指针。当你用一个运算符&指向一个数组时,你产生一个指向数组最初元素的指针;当您将数组隐式转换为指针时,您还会获得指向数组最初元素的指针。因此,对于&str1str1%p的两个打印输出产生相同的值0x7ffe95676bf0

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

如果你开始的str2地址,即

char *str2 = "Goodbye"; 
char **ptrStr2 = &str2; 

您可以通过提领得到"Goodbye"位置,即

printf("%p %s\n", (void*)*ptrStr2, *ptrStr2); 

Demo.

+0

非常感谢您的有用答复。我能再问一个问题吗?如果你使用'%p',它是否需要转换为'void *'?如果是的话 - 为什么这是必要的? –

+0

@articsol是的,除char和unsigned char指针之外的所有指针都是必需的,它们保证与void指针具有相同的表示形式。 %p假定你传递了一个void指针,所以你需要添加一个转换以确保传递正确的表示。 – dasblinkenlight

+0

非常感谢 –

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

所以因为使用了转换说明%d与指针这些调用

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

是错误的。

我的问题是,有没有办法打印地址阵列再见使用 指针* 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