2014-02-05 29 views
0

我遇到了一個有趣的輸出,我想知道計算機是如何工作的。我知道,只要你有%d的字符串,你應該有一個變量來陪伴它。當我寫了兩個%d和只有一個變量時,我預計計算機會爲%d創建相同的值,因爲它只有一個變量可供使用,但由於某種原因,%d返回了x的值和變量xCubed的值。我想知道爲什麼程序返回xCubed而沒有在字符串末尾寫入xCubed。代碼如下:在C中,有關%d如何識別字符串變量的技術說明

#include <stdio.h> 

int cube(int x); 

int main(void){ 
    int x = 5; 
    int xCubed = cube(x); 

    printf("Why does this number, %d, equal this number %d?", x); 

    return 0; 
} 

int cube(int x){ 
    return x * x * x; 
} 

謝謝!

+0

UB的最大... –

回答

3

這是因爲xCubed恰好在x後面分配,這意味着更接近堆棧(激活幀)的printf部分。

printf是一個可變參數函數,它不知道它傳遞了多少個參數。所以,當你用兩個佔位符調用printf,但只提供了一個值時,它會讀取第一個參數,期望第二個參數和「下降」到調用方的棧中,其最近的內容正好是xCubed

要明確一點:這就是爲什麼你的代碼表現出特定的行爲,而不是預期的工作方式。你的代碼中有一個嚴重的錯誤。

5

您的程序調用未定義的行爲。什麼事情都可能發生。可能從呼叫cube返回的價值恰好位於堆棧上x的值旁邊。當然,這種行爲未定義意味着對程序或編譯器選項的任何更改都可能導致不同的行爲。

在任何情況下,您都需要提供兩個值。這樣做。

printf("Why does this number, %d, equal this number %d?", x, x); 

如果您編譯完整的警告程序,然後編譯器會警告你你的錯誤。甚至可以讓編譯器將警告視爲錯誤來阻止你犯下錯誤。

+2

有很多關於未定義行爲的推理點。有些人不僅要了解C標準,還要了解處理器的工作方式,編譯器的工作方式等等。 「未定義行爲」在這個論壇中經常被使用,這意味着只有C標準沒有對其進行定義,而不是世界上其他事物沒有定義它。 –

4

你的程序導致未定義的行爲,所以任何事情都是可能的。這是你的平臺的堆棧/寄存器佈局和調用慣例的一些怪癖,給你看到的結果。

2

這是好運。實際上,這是未定義的行爲。

顯然,在你的情況下,變量xCubed立即放在堆棧後的可用空間。在執行printf()調用之後,x立即被放置,然後是格式字符串的地址。

如果使用其他優化設置編譯該程序,編譯器可能會決定將xCubed放在其他地方或寄存器中,或者完全忽略它,因爲它的值從不使用。