字符指针和printf函数 [英] Char pointers and the printf function
问题描述
我试图学习指针,并且编写了以下代码来打印指针的值:
I was trying to learn pointers and I wrote the following code to print the value of the pointer:
#include <stdio.h>
int main(void) {
char *p = "abc";
printf("%c",*p);
return 0;
}
输出为:
a
但是,如果我将上面的代码更改为:
however, if I change the above code to:
#include <stdio.h>
int main(void) {
char *p = "abc";
printf(p);
return 0;
}
我得到输出:
abc
abc
我不明白以下两件事:
-
为什么在第二种情况下printf不需要格式说明符?
printf(pointer_name)
是否足以打印指针的值?
why did printf not require a format specifier in the second case? Is
printf(pointer_name)
enough to print the value of the pointer?
(很少),* p指向包含abc
的连续内存块.我希望两个输出都相同,即
as per my understanding (which is very little), *p points to a contiguous block of memory that contains abc
. I expected both outputs to be the same, i.e.
abc
abc
由于打印方式不同,输出是否不同?
are the different outputs because of the different ways of printing?
编辑1
此外,以下代码会产生运行时错误.为什么这样?
Additionally, the following code produces a runtime error. Why so?
#include <stdio.h>
int main(void) {
char *p = "abc";
printf(*p);
return 0;
}
推荐答案
For your first question, the printf
function (and family) takes a string as first argument (i.e. a const char *
). That string could contain format codes that the printf
function will replace with the corresponding argument. The rest of the text is printed as-is, verbatim. And that's what is happening when you pass p
as the first argument.
请注意,强烈建议不要以这种方式使用printf
,尤其是如果字符串包含用户输入的内容时.如果用户在字符串中添加了格式代码,而您没有提供正确的参数,那么您将具有未定义的行为.甚至可能导致安全漏洞.
Do note that using printf
this way is highly unrecommended, especially if the string is contains input from a user. If the user adds formatting codes in the string, and you don't provide the correct arguments then you will have undefined behavior. It could even lead to security holes.
对于第二个问题,变量p
指向一些内存.表达式*p
取消引用指针以给您一个字符,即p
实际指向的字符,即p[0]
.
For your second question, the variable p
points to some memory. The expression *p
dereferences the pointer to give you a single character, namely the one that p
is actually pointing to, which is p[0]
.
这样想p
:
+---+ +-----+-----+-----+------+
| p | ---> | 'a' | 'b' | 'c' | '\0' |
+---+ +-----+-----+-----+------+
变量p
并不真正指向字符串",它仅指向内存中的某个单一位置,即字符串"abc"
中的第一个字符.使用p
的功能会将内存视为字符序列.
The variable p
doesn't really point to a "string", it only points to some single location in memory, namely the first character in the string "abc"
. It's the functions using p
that treat that memory as a sequence of characters.
此外,常量字符串文字实际上存储为字符串中字符数的(只读)数组,再加上一个用于字符串终止符的数组.
Furthermore, constant string literals are actually stored as (read-only) arrays of the number of character in the string plus one for the string terminator.
此外,为了帮助您理解为什么*p
与p[0]
相同的原因,您需要知道对于任何指针或数组 p
和有效索引i
,表达式p[i]
等于*(p + i)
.要获得第一个字符,您必须具有索引0
,这意味着您具有p[0]
,然后应等于*(p + 0)
.向任何事物添加零是无操作的,因此*(p + 0)
与*(p)
相同,而*(p)
与*p
相同.因此p[0]
等于*p
.
Also, to help you understand why *p
is the same as p[0]
you need to know that for any pointer or array p
and valid index i
, the expressions p[i]
is equal to *(p + i)
. To get the first character, you have index 0
, which means you have p[0]
which then should be equal to *(p + 0)
. Adding zero to anything is a no-op, so *(p + 0)
is the same as *(p)
which is the same as *p
. Therefore p[0]
is equal to *p
.
关于您的编辑(在其中执行printf(*p)
),由于*p
返回由p
指向的第一个元素"(即p[0]
)的值,因此您要传递单个字符作为格式字符串的指针.这将导致编译器将其转换为指针,该指针指向具有该单个字符值的任何地址(它不会将字符转换为指针至的指针).此地址不是一个非常有效的地址(在 ASCII字母 'a'
具有值97
是程序将在其中查找要打印的字符串的地址),您将具有未定义的行为.
Regarding your edit (where you do printf(*p)
), since *p
returns the value of the first "element" pointed to by p
(i.e. p[0]
) you are passing a single character as the pointer to the format string. This will lead the compiler to convert it to a pointer which is pointing to whatever address has the value of that single character (it doesn't convert the character to a pointer to the character). This address is not a very valid address (in the ASCII alphabet 'a'
has the value 97
which is the address where the program will look for the string to print) and you will have undefined behavior.
这篇关于字符指针和printf函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!