2011-04-06 32 views
2

這裏是一塊代碼,我不明白數組的指針,更用C

#include "malloc.h" 

/*some a type A and type for pointers to A*/ 
typedef struct a 
{ 
    unsigned long x; 
} A, *PA; 

/*some a type B and type for pointers to B*/ 
typedef struct b 
{ 
    unsigned char length; 
    /*array of pointers of type A variables*/ 
    PA * x; 
} B, *PB; 

void test(unsigned char length, PB b) 
{ 
    /*we can set length in B correctly*/ 

    b->length=length; 

    /*we can also allocate memory for the array of pointers*/ 

    b->x=(PA *)malloc(length*sizeof(PA)); 

    /*but we can't set pointers in x*/ 

    while(length!=0) 
     b->x[length--]=0; /*it just would not work*/ 
} 

int main() 
{ 
    B b; 
    test(4, &b); 
    return 0; 
} 

任何人都可以在概念上闡述對我,爲什麼我們不能在數組x組指針測試()?

+0

這不起作用?含義,它不會編譯?或者沒有按預期行事? – 2011-04-06 14:41:37

+0

'malloc.h'不是標準的C頭。使用'stdlib.h'。 – 2011-04-06 14:41:38

+0

我不認爲這是關於編譯器或頭文件。我使用VS2010編碼,項目類型爲空控制檯。 – 2011-04-06 14:49:49

回答

4

在test()的最後一行,您將初始化陣列末尾的位置。如果你的長度是4,那麼你的數組長4個指針。 b-> x [4]是數組的第5個元素,因爲第1個元素是b-> x [0]。你需要改變你的while循環值從0迭代長度 - 1

+3

你的意思是他可以做 - 長度而不是長度 - 對嗎? – 2011-04-06 14:48:57

+0

是的,這將使循環正常工作。 – 2011-04-06 14:52:59

+0

@ Y.Z:你在調試模式下編譯? – 2011-04-06 15:31:13

-1

我假設你正在試圖零所有的無符號多頭A的內B.

指向數組中是否有這裏有 - >和[]運算符的優先問題?

嘗試:

(b->x)[length--] = 0; 

也許改變

typedef struct a 
{ 
    unsigned long x; 
} A, *PA; 

typedef struct a 
{ 
    unsigned long x; 
} A; 
typedef A * PA; 

+1

這些都不是問題。 – 2011-04-06 15:14:38

0

我只是增加了在主一個printf測試b.length個和BX []價值觀和一切工作。 只需在return之前加上printf("%d, %d %d %d %d", b.length, b.x[0], b.x[1], b.x[2], b.x[3]);即可。

它給出了4,0,0,0,0這是我認爲你期望沒有?或者它是算法錯誤

1

如果要在b->x中將每個PA設置爲空,那麼應該寫--length而不是length--來完成這項工作。
顯然試圖找出--所屬的地方是令人困惑的。你最好寫:

unsigned i; 
for (i = 0; i < length; i++) 
    b->x[i] = 0; 

但事實上,在這種情況下,你可以簡單地使用:

memset(b->x, 0, length*sizeof(PA)); 
+0

問題在於減少前後運算符的區別。不同之處在於--length操作將首先減小長度,然後返回值長度。 length--將首先返回長度,然後減小值的長度。 – spade78 2011-04-06 17:41:12

1

你的結構更加動態內存分配的一個層次複雜得多,通常是必要的。您有:

typedef struct a 
{ 
    unsigned long x; 
    ...and other members... 
} A, *PA; 

typedef struct b 
{ 
    unsigned char length; 
    PA * x; 
} B, *PB; 

B的最後一個成員是struct a **,這可能是必要的,但是實際上卻很少。你或許應該通過簡化一切:

typedef struct a 
{ 
    unsigned long x; 
} A; 

typedef struct b 
{ 
    unsigned length; 
    A  *array; 
} B; 

這改寫體現了面對的typedef個人偏見的指針(讓我消除PA和PB)。我將B中的length的類型從unsigned char更改爲unsigned;使用unsigned char節省了所示設計的空間,但如果您將分配長度與使用長度分開記錄(但即使如此,我可能會使用unsigned short而非unsigned char),但可能會節省空間。

而且,最重要的是,它改變了數組的類型,因此您沒有爲每個元素指定單獨的指針,因爲數組本身包含元素。現在,偶爾,你確實需要處理指針數組。但是這是相當不尋常的,它絕對會使內存管理複雜化。

的代碼在你的test()功能簡化:

void init_b(unsigned char length, B *b) 
{ 
    b->length = length; 
    b->x = (A *)malloc(length*sizeof(*b->x)); 
    for (int i = 0; i < length; i++) 
     b->x[i] = 0; 
} 

int main() 
{ 
    B b; 
    init_b(4, &b); 
    return 0; 
} 

使用慣用for環路避免步進出界(在原代碼的問題之一)的。分配的內存的初始化循環可能可以替換爲memset()操作,也可以使用calloc()而不是malloc()

您的原始代碼是將指針數組中的指針設置爲null;您無法訪問任何數據,因爲沒有數據;您尚未爲實際值struct a分配空間,只是指向這些值的指針數組的空間。

當然,代碼應該檢查內存分配是否失敗,或者爲內存分配器使用一個覆蓋函數,以保證內存分配失敗時不會返回。假設內存分配在沒有檢查的地方會成功是不安全的。分配器的封面功能通常使用xmalloc()emalloc()等名稱。

別人指出malloc.h是非標準的。如果您正在使用它提供的調整工具或它提供的報告工具,那麼malloc.h就沒有問題(但它不在任何地方都可用,因此它會限制代碼的可移植性)。然而,大多數人大多數時候應該忘記malloc.h並使用#include <stdlib.h>代替;使用malloc.h是從C89標準前幾天開始思考的一個標誌,當時沒有標題宣佈爲malloc()等,並且這是時間之前。


另請參閱Freeing 2D array of stack;那裏的代碼和這段代碼是同構的(你是在同一個班級嗎?)。我在那裏推薦和說明了相同的簡化。