2013-04-09 51 views
1

背後的原因,我已經做了測試,其中就出現了這樣的事情:這個輸出

char* trim(char* strr, char* str1) { 
    char* s = strr; 
    while(*str1 == 32) str1++; 
    while((*str1 != 32) && (*str1 != 0)) 
     *s++ = *str1++; 
    *s = 0; 
    return strr; 
    } 

int main(void) { 
    char str[20] = "???"; 
    char str1[20] =" bcd \0"; 

    printf("(%s)\n(%s)\n", str, trim(str, str1)); 
    return(0); 
} 

的問題是:什麼上面的代碼將打印,爲什麼?我對輸出結果和原因有了一些線索,但我希望聽到更多有經驗的人士的意見。

乍一看,它看起來像它會打印:

(???) 
(bcd) 

但在現實中產生的輸出是:

(bcd) 
(bcd) 
+0

是不是你覆蓋str? – 2013-04-09 23:50:27

+0

@JaynathanLeung這個功能沒有完成,我只是複製和過去。 – dreamcrash 2013-04-09 23:51:44

+0

由於trim是一個參數並在printf之前運行,所以well str正在被修剪覆蓋。 – 2013-04-09 23:52:40

回答

2

[編輯:刪除以前的答案,這@Nigel哈珀是不錯足夠有禮貌地指出是完全無稽之談。]

printf(所有參數)的參數在執行之前以某種未指定的順序進行評估printf本身就開始了。因此,在printf開始執行時,str和(重要)trim(str, str1)都已被評估。

由於trim(str, str1)修改存儲器str點,其本身正在執行時間printf,存儲器指向由str將已被修改以包含bcd(顯然,指針從trim(str, str1)返回的意志爲好) 。

因此,無論評估兩個參數的順序如何,兩個輸出都將是bcd

+0

有趣的是,我認爲printf參數將首先被評估,而不是打印出來。 – dreamcrash 2013-04-09 23:52:57

+0

我不認爲評估順序是相關的。所有評估都會產生指針值 - 它不會查看字符串,只發生在printf中。重要的是,trim一定會首先被調用,所以printf只能看到str的內容,而不是原來的。 – 2013-04-10 00:02:27

+0

我更喜歡這個版本後的答案,因爲它與我在測試時的回答相似:) – dreamcrash 2013-04-10 00:11:27

1

您正在調用str函數中的strr。由於它是通過引用傳遞的,因此該更改會反映回調用函數。 printf將得到str的評估副本(兩個參數都相同)。

0

最後一個參數是先評估,先推到堆棧。但評價論點的順序並不明確。

我裝箱一個簡單的代碼:

#include <stdio.h> 

char *go(char *s) { *s = '0'; return s; } 

int main() { 
    char str[] = "xyz", str1[] = "abc"; 
    printf("(%s)(%s)\n", str, go(str)); 
    printf("(%s)(%s)\n", go(str1), str1); 
} 

輸出:

(0yz)(0yz) 
(0bc)(0bc) 

您可以分析這個gcc命令行彙編輸出:

gcc -c -g -Wa,-a,-ad x.c >x.lst 

如果添加-02順序相同,但go()函數變爲內聯。

嗯......我又學到了一些東西!謝謝!

+0

我只是改變了參數的順序,並且發生了同樣的情況 – dreamcrash 2013-04-09 23:57:21

+0

你和傑夫是對的!堆棧中參數的順序是明確的。最後是先推。但評價論點的順序並不明確!我修改我的答案! – TrueY 2013-04-10 07:59:51

+0

Np,謝謝你的回覆。 – dreamcrash 2013-04-10 12:36:04