2015-10-28 28 views
2

這裏是我的代碼,我發現「each」宏只迭代第一個元素並輸出「s1」,如何讓它迭代所有元素?c「each」macro does not iterate all elements

#include "stdio.h" 

#define each(item, array) \ 
    for (int keep = 1, count = 0, size = sizeof(array)/sizeof *(array); keep && count != size; keep = !keep, count++) \ 
     for (item = array[count]; keep; keep = !keep) 

char *join(char const *ss[]) { 
    char *r = ""; 
    each(char *s, ss) { 
      puts(s); 
     } 
    return (r); 
} 

int main(int argc, char **argv) { 
    char const *ss[] = {"s1", "s2"}; 
    join(ss); 
}; 
+1

請不要寫這樣的宏;不要試圖改變C語言。你可以假設每個其他的C程序員都知道C.你不能假設他們知道或關心瞭解你的家庭釀造的祕密宏語言。這是非常糟糕的編程習慣。 – Lundin

+0

在一個名爲'each'的宏中放置一個雙嵌套循環並不是一個好主意。這個邏輯比你可以考慮的「樣板」更復雜。另外,當你做的功能不像函數時,你應該使用大寫宏名稱。 (例如,如果使用GNU C特性來避免多次評估它的參數,那麼'max'宏可能沒問題。) –

回答

1

如果你打電話eachmain,即其中ss定義的地方,你的程序按預期工作:

int main(int argc, char **argv) { 
    char const *ss[] = {"s1", "s2"}; 

    each(char *s, ss) { 
     puts(s); 
    } 
}; 

它的工作原理,因爲each訪問ss聲明,讓sizeof a/sizeof *a等於元素的個數在陣列中。

問題是,如果你通過ss數組到另一個函數(例如join),它decays to pointer。由於ssjoin是一個指針,sizeof array不再指數組的大小,並且表示sizeof a/sizeof *a產生sizeof(char**)/sizeof(char*)這就是你的平臺上的1

又見

What is array decaying?

+0

你說得對,我使用可變參數來重寫#加入 – nwaicaethi

0

考慮以下術語

for(initialization statement; condition; update statement) { 
     code/s to be executed; 
} 

condition有一個說法keep && count != size;它正在檢查keep值是非零。

而在update statement你正在做keep = !keep這是使keep0

因此,您的循環正在單次迭代中退出。相應地修改您的條件以多次循環。

+0

這是沒有理由的,我保持!=保持兩次 – nwaicaethi

0

這裏的宏沒有創造,只要你使用的任何問題,只是宏代碼的地方,

你需要檢查你的for循環,

size = sizeof(array)/sizeof *(array); 

在上述聲明sizeof(array)sizeof *(array)都被賦予sizeof指針。所以size總是1。

接下來是在裏面或第二個for循環迭代只有一次,因爲你做了keep = !keep它改變了keep = 0;

所以現在完成了第一次迭代中,它要更新keep = !keep, count++),之後,它檢查車況keep && count != size這個

keep = 1; 

count= 1;

size = 1; 

因此被終止循環,所以檢查你的循環條件部分。

,如果你有意向,只是重複的字符數組,然後也有解決方案數量的所有項目做到這一點,我剛剛上市代碼中的其中一個改變

在宏觀

for (int keep = 1, count = 0, size = sizeof(ss)/sizeof *(ss); ss[count] != "\0"; keep = !keep, count++) \ 

在主要功能

char const *ss[] = { "s1", "s2","\0" }; 

現在您將獲得預期的輸出。