2017-07-17 60 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開始的索引)。

也就是說,正如前一段強調的那樣,指針算術只對加法有效,而不是乘法運算符。