2013-02-19 50 views
4

我只是最近才瞭解到,我實際上可以在C中使用對複合文字數組的引用,我發現它很有用,但我不太明白它是如何工作的。引用的複合數組文字的生存期

例如,說我使用的功能,以避免必須聲明一個變量爲一個呼叫,我不計較回報名長度有一定的套接字接口的功能,如:

int sockfamily(int fd) 
{ 
    struct sockaddr_storage ss; 

    getpeername(fd, (struct sockaddr *)&ss, (socklen_t [1]){sizeof(ss)}); 
    return(ss.ss_family); 
} 

顯然,sizeof(ss)需要實際存儲在堆棧中,以便指向它的指針傳遞到getpeername,因此堆棧上的空間必須爲此分配和保留,但該分配的生命週期是多少?我可以信任它多久才能繼續分配?

看看海灣合作委員會的彙編輸出,我觀察到如果我把getpeername的調用放到一個循環中,那麼分配不會在循環的多次迭代中存活,那麼其他什麼條件可能會導致它停止存在?

+0

對於結構:http://stackoverflow.com/questions/21882564/what-is-the-lifetime-of-compound-literals-passed-as-arguments/31178926#31178926 – 2015-07-02 08:08:36

回答

11

A 複合文字定義在一個函數中具有與包含它的塊相關聯的自動生命期(即與在同一級上聲明的變量相同的生存期)。這在標準6.5.2.5p5中有規定。

int f() { 
    for (int i = 0; i < 10; ++i) { 
     int *j = (int []){i}; // storage duration of loop body 
    } 
} 

這基本上意味着,複合字面常量相當於申報並在同一範圍內初始化的變量:

int f() { 
    for (int i = 0; i < 10; ++i) { 
     int __unnamed[] = {i}; 
     int *j = __unnamed; 
    } 
}  

小心,如果通過複合文字的任何地方,它們的指針會堅持過去他們的一生:

int f() { 
    int *p; 
    if (1) { 
     p = (int []){0, 1, 2}; 
     assert(p[0] == 0); 
    } 
    // *p is undefined 
} 
+0

謝謝對標準的參考!這非常有幫助。 – Dolda2000 2013-02-19 19:29:48

+0

給出類似'void blah(void){struct foo * f; ... foo = somefunc(); if(foo == NULL)f =(struct foo *){data}; ...}'是否有任何干淨的方法讓'if'控制多於一個語句? – supercat 2015-07-21 21:01:11

+0

@supercat如果我理解正確,你可以嘗試類似'struct foo * fallback [] = {data}; if(f == NULL)f = fallback;' - 但那樣你就不需要複合文字了。 – ecatmur 2015-07-22 07:34:59