2017-07-17 96 views
3
#include <stdio.h> 

void main() { 
    printf(2 + "abcdefgh"); 
} 

此代码是如何打印的cdefgh?如果我使用2-2*或任何其他运算符,编译器会报错。在printf中使用(+ ve integer)+“一些字符串”?

+8

如果您知道“2 + any_pointer”等于“any_pointer + 2”,它等于'&any_pointer [2]',那么可能更有意义。 ' –

+0

'“格式字符串是一个字符串,以其初始移位状态开始和结束”' –

+0

反正你甚至用'2 *“abcdefgh”'期待什么? –

回答

2

当使用字符串文字(如"abcdefgh")时,您实际上有一个指向此字符串所在的内存部分的指针。基本上,你传递给printf一个指针到该位置,并指示提前2点位置移动指针,导致串从3炭,而不是第一

注意,您可以使用-开始,但你需要使用像你一样的指针运算,像

printf("abcdefgh" - 0); // using -N where N >0 would be UB

所以,这个代码是有效的

int main() 
{ 
    printf("abc\n" - 0); 
    printf(1+"def"); 
    return 0; 
} 

但使用*,/不会(并且按位运算符|,&将无效)

3

在此代码

printf(2 + "abcdefgh"); 

相同

printf(&("abcdefgh"[2])); 

其中,所述参数作为在printf()格式字符串。

为了详细描述,从字符串文字的性质,引用C11,章§6.4.5/ P6

在翻译阶段7中,零值字节或码被附加到每个多字节 由一个或多个字符串引起的字符序列。 78)然后使用多字节字符 来初始化静态存储持续时间和长度的数组,这足以包含该序列。对于字符串文字,数组元素有 类型char,并且使用多字节字符 序列的单个字节进行初始化。 [...]

和用于阵列,从章§6.3.2.1,

除了当它是sizeof操作者的操作数时,操作者_Alignof或 一元&操作者,或者是用于初始化数组的字符串文字,将具有类型'''的类型数组''的表达式转换为类型''指向类型''的表达式的表达式,该表达式将 指向数组对象的初始元素并不是左翼。 [...]

所以,在函数调用的参数的情况下,作为加法运算符的一个参数,字符串常量实际上波士下降到第一个元素的地址在文字,然后,此外,这是一个指针算术,发生。结果是增量指针指向第三个元素(C数组是从0开始的索引)。

也就是说,正如前一段强调的那样,指针算术只对加法有效,而不是乘法运算符。