2016-03-04 85 views
2

我正在使用一個很好的GCC擴展,它允許我們在結構中聲明VLA。現在我發現了一種通過這種方式將VLA傳遞給函數的方法(通過值)。我也找到了一種方法來回報一個,但在一個非常有限的情況下。如何在每個函數實例上返回大小不同的VLA?

本實施例的功能碼是這樣的:

extern void func3() 
{ 
    size_t size; 

    scanf("%zu", &size); 

    struct tx{int _[size];} fn() 
    { 
     struct tx rt; 

     for(size_t i=0; i < size; ++i) 
      scanf("%d", &rt._[i]); 

     return rt; 
    } 

    volatile __typeof__(fn) *pf = fn; 
} 

上面的例子被設計用於測試目的(特別是比較編譯它的二進制代碼)。

但是,這是相當有限的,因爲函數的不同調用之間返回數組的大小不變。

如何使返回的數組大小等於函數參數之一或本函數中的某個其他本地參數。

我不認爲alloca可以幫助我的情況下,因爲它分配的內存立即銷燬在函數出口(IRC)。

我想寫的東西是這樣的:

/*???*/ func5() 
{ 
    size_t size; 

    scanf("%zu", &size); 

    struct {int _[size];} rt; 

    for(size_t i=0; i < size; ++i) 
     scanf("%d", &rt._[i]); 

    return rt; //ok - return the structure 
} 

換句話說,這可能是問號裏面的類型?或者也許有其他解決方案(但不使用malloc)?

這樣的功能的理論使用將理論上需要另一種類型的存儲返回值作爲返回的結構體的大小將不提供給調用者(除非有某種方式避免這種?)。但在第一眼看到它應該是這樣的

size_t size; 

//scanf("%zu", &size); 

struct {int _[size];} tmp; //create locally VM type 
          //compatible with the one 
          //returned by our theoretical func5 

          //we can't directly initialize tmp here (gcc complains) 


tmp = ((__typeof__(tmp) (*)())func5)(); //direct assignment between VM structures 
             //works here on the other hand 

             //as function return value is rvalue and we can't 
             //take its pointer and cast it to our local VM structure type 
             //we instead cast the function pointer 

如果我們做這樣的事情

__typeof__(func5()) tmp = func5(); 

它不會因爲虛擬機返回類型的func5工作將要麼依賴於它的參數或局部變量。 但是,這一切都是理論上的,因爲我們仍然不能定義這個功能

+1

只是讓呼叫者第一分配陣列和被叫只是在填入值。 – user3528438

+0

@ user3528438我對其他解決方案不感興趣。我希望將VLA分配保存在被調用的函數中(並且不使用'malloc')。 – AnArrayOfFunctions

+0

我想看看這是如何編碼的。像'{type_TBD func5(); type_TBD y = func5(); //使用y}'?你能發表一些使用'func5()'結果的理論代碼嗎? – chux

回答

2

[..]我希望VLA分配保持在被調用函數中(並且不使用malloc)。

只有兩個來源的動態內存存儲在C程序的常見託管實現:堆和堆棧。

你不想使用第一個,但第二個是自動管理:無論你分配一些功能的「內幕」,將「水漲船高」當函數返回。

唯一例外的是 - 當然 - 返回值。這沒有太大的幫助,但是,因爲爲了留在堆棧上爲它的內存(如果通過堆棧返回)被「分配之下」的函數調用的參數。因此,在調用函數之前必須知道它的大小(否則不知道在哪裏存儲參數,函數的局部變量等等)。由於「在堆棧上的分配」基本上與「按照已知數量的字節前進某個指針」相同,這裏有一個矛盾:你想在函數內部分配,但是在進入之前需要知道多少功能。

這是行不通的。

+0

也許它會,如果我可以從參數中獲取大小(與傳遞VLA相同)。然而,現在這在語法上是不可能的,因爲函數參數在指定函數返回類型時不可見。但也許有其他的方式知道。 – AnArrayOfFunctions

2

如何返回每個函數實例的大小不同的VLA?

返回一個VLA是一回事,除非它被傳入(那麼返回它的意義是什麼),它是不可行的。調用代碼無法接收它,除非其大小事先已確定。


也許這已經足夠接近OP的目標。

使用在已知大小但在調用func5()之前分配的VLA。

typedef struct { 
    size_t size; 
    int *a; 
} va; 

void func5(va *p) { 
    for (size_t i = 0; i < p->size; ++i) { 
    // error handling not shown 
    // scanf("%d", &p.a[i]); 
    p->a[i] = i; 
    } 
} 

int main(void) { 

    // create 
    size_t size = 5; 
    // scanf("%zu", &size); 
    int v[size]; 
    va t = { size, v }; 

    // populate 
    func5(&t); 

    // use 
    for (size_t i = 0; i < size; i++) { 
    printf("%d\n", t.a[i]); 
    } 

    // automatic "free" 
    return 0; 
} 

輸出

0 
1 
2 
3 
4 
+0

恕我直言,這是解決這個問題的正確方法,儘管你可能應該擺脫那個結構,只傳遞指針和大小。 –

相關問題