为什么直接将字符串传递给printf正常工作?

时间:2016-06-23 21:04:23

标签: c string pointers printf

我知道在C中这两件作品都是:

char* string = "foo";
printf("string value: %s", string);

更简单:

printf("string value: %s", "foo");

但我问自己为什么。

我知道%s标识符要求参数为char *,string实际上是(并且它与字符数组相同,因为这两种数据类型是相同的在C)

但是当我直接将字符串传递给printf时,它应该不同吗?我的意思是"foo"不再是指针......对吗?

5 个答案:

答案 0 :(得分:6)

字符串常量"foo"的类型为char []。当传递给函数时,数组衰减为指针,即char *。所以你可以把它传递给一个期望相同的函数。

出于同样的原因,您还可以传递此类型的变量:

char string[4] = "foo";
printf("string value: %s", string);

答案 1 :(得分:2)

"foo"是字符串文字。它表示一个未命名的数组对象,其静态存储持续时间类型为char[4](即没有 const限定符),它按值传递给函数,就像它一样任何“正常”阵列。

即使数组不是const,也不允许修改其值。这种修改会导致未定义的行为:

char* string = "foo";
string[0] = 'b'; // wrong, this invokes UB

该数组有四个元素,因为尾随空字符 '\0',有时称为NUL字符。请不要将其与NULL混淆,这是另一回事。该字符的目的是终止给定的字符串文字。

函数的参数接收指向char的指针,因为数组对象转换指向数组第一个元素的指针(即指向数组中第一个字符的指针)。确切地说,不是传递整个指针,只传递它所持有的地址(即指针的值)。

答案 2 :(得分:1)

在C中,所有字符串都以null结尾char [],因此您的示例将以相同的方式进行交互。

ISO C标准第7.1.1节以这种方式定义字符串:

  

字符串是以和结尾的连续字符序列   包括第一个空字符。

答案 3 :(得分:0)

printf()得到什么,指针:

ISO / IEC 9899:TC3,6.5.2.2 - 4:

  

参数可以是任何对象类型的表达式。在准备对函数的调用时,将对参数进行求值,并为每个参数分配相应参数的值.81)

     

81)声明具有数组或函数类型的参数被调整为具有6.9.1中描述的指针类型。

ISO / IEC 9899:TC3,6.9.1-10:

  

在进入函数时,将评估每个可变修改参数的大小表达式,并将每个参数表达式的值转换为相应参数的类型,就像通过赋值一样。 (数组表达式和函数指示符作为参数在调用之前转换为指针。

答案 4 :(得分:-1)

最后,

"foo"是一个指针文字,指向静态分配的4字节内存区域(可能标记为只读),用内容初始化:'f'。 'o','o','\ 0'。