#include <stdio.h>
void main() {
printf(2 + "abcdefgh");
}
此代码如何打印cdefgh
?如果我使用2-
或2*
或任何其他运算符,编译器会抛出错误。
当使用字符串文本(如"abcdefgh"
(时,您实际上有一个指向此字符串所在的内存部分的指针。基本上,您将指向该位置的指针传递给printf
并指示它将指针向前移动 2 个位置,从而产生从第 3 个字符而不是第一个字符开始的字符串
请注意,您可以使用-
但您需要像使用指针算术一样使用它,例如
printf("abcdefgh" - 0); // using -N where N >0 would be UB
所以,这个代码是有效的
int main()
{
printf("abcn" - 0);
printf(1+"def");
return 0;
}
但是使用*,/
不会(按位运算符|,&
也将无效(
在此代码中
printf(2 + "abcdefgh");
与
printf(&("abcdefgh"[2]));
其中,参数用作printf()
中的格式字符串。
为了详细说明,从字符串文字的属性中,引用C11
,第 §6.4.5/P6 章
在转换阶段 7 中,值为零的字节或代码附加到每个多字节 由一个或多个字符串文本生成的字符序列。78(多字节字符 然后使用序列来初始化静态存储持续时间和长度的数组 足以包含序列。对于字符串文本,数组元素具有 键入
char
,并使用多字节字符的各个字节进行初始化 序列。[...]
对于数组,来自第 §6.3.2.1 章,
除非它是
sizeof
运算符、_Alignof
运算符或 一元&
运算符,或者是用于初始化数组的字符串文本,该表达式具有 类型"类型数组"转换为类型为"指向类型的指针"的表达式,该表达式指向 到数组对象的初始元素,并且不是左值。[...]
因此,在函数调用参数的情况下,作为加法运算符的参数之一,字符串文字实际上向下移动到文字中第一个元素的地址,然后,加法(指针算术(发生。结果以递增的指针表示,该指针指向第三个元素(C 数组是从 0 开始的索引(。
也就是说,正如上一段所强调的,指针算术仅对加法运算有效,而对乘法运算符无效。