为什么在C语言中,指针可以在不进行解引用的情况下打印其内容?
为什么在C语言中,指针可以在不进行解引用的情况下打印其内容?
这个问题在这里已经有了答案:
我创建了一个程序,发现两件事情
- 我使用指针地址打印整个单词,它可以工作,但当我用*s替换s时,它就不能工作了(这是为什么?) (我在printf中使用地址,而不是*s的内容)
- 当我使用指向指针的指针打印字符时,我什么都打印不出来(我是说当我用%c替换%s时)
我的代码:
#include int main () { char str[10]="PinkFloyd"; char *s; char **s1; s=&str[0]; s1=&s; printf("the word is using pointer to pointer %s",*s1); //why if I used %c does not print the first character printf("\n"); printf("the word is using s pointer %s",s); // why if I had replaced with *s does not print anything return 0; }
%s
格式说明符打印由参数指向的以空字符结尾的字符串。这意味着它从参数中的地址开始,每次打印一个字符,直到达到0
(不是字符,而是实际数字值0
)为止。
在您的情况下,s1
是一个指向char
指针的指针,字符串的第一个字符,因此反引用的*s1
是指向以空字符结尾的字符串的指针。变量s
是一个指向char
的指针,因此反引用的*s
是一个字符。
如果您使用了用于打印以空字符结尾的字符串(%s
)的格式说明符并传递了一个常规字符,则会将数字值(所有字符都是数字值)传递给printf
方法,并尝试读取它,就好像它是应该从中读取字符串的内存地址。%c
另一方面期望数字是单个字符,而不是内存地址。
如果要打印第一个字符(%c
),则对于s1
,您必须使用**s1
,对于s
,您必须使用*s
。如果要打印整个字符串(%s
),则必须指向要打印的字符串的第一个字符,因此对于s1
,将是*s1
,对于s
,您必须使用s
(它已经是指向char
的指针)。
// Print the entire string const char *s = "Some String"; printf("%s", s); // Prints: // Some String // Move the pointer and start inside the string printf("%s", s + 5); // Prints: // String // Print a single character printf("%c", *s); // Prints: // S // Create a pointer to a pointer to s const char **ps = &s; printf("%s", *ps); // Prints: // Some String // Print the first character printf("%c", **ps); // Prints: // S
在上面的示例中,s==*ps
,因此当您反引用指向指针的指针时,您最终得到的是指向某个东西的指针。您可以在此处阅读有关printf
-类函数的不同格式说明符的更多信息:https://en.cppreference.com/w/c/io/fprintf#Parameters
你不需要使用*
打印一个字符串,因为实际上printf
会为你做这件事。
当你使用%s
和printf
一起使用时,你并没有实际上将你的字符串传递给printf
。你传递的是指向该字符串第一个字符的指针,printf
会负责遍历字符串并打印出它的所有字符。
这与在C语言中处理字符串的方式并没有任何不同。字符串是数组,但数组在C语言中是“二等公民”,这基本上意味着你永远不会将它们全部传递。几乎在C语言中的每个库函数工作与字符串一起使用时都是使用指向它们第一个字符的指针。
如果你调用了
printf("%s", *s); /* WRONG */
它就不起作用。 *s
会给你指向指针的内容,它是字符'P'
。但%s
想要的是一个指针,而不是一个字符。
你也许还会发现这个问题及其答案有趣。