2009-10-16 19 views
6

Làm cách nào để viết mã của tôi để ví dụ một chỉ mục mảng cụ thể của một mảng có thể là thành viên của cấu trúc? Các mã sau đây là cho tôi vấn đề.Trong C: Làm thế nào để thiết lập một con trỏ đến một cấu trúc thành viên đó là một mảng?

// main.c 

void clean_buffers(void); // prototype 

struct DEV_STATUS { 
    unsigned char ADDR; 
    unsigned char DEV_HAS_DATA; 
    unsigned char ETH_HAS_DATA; 
    unsigned char DATA[20]; 
}; 

struct DEV_STATUS g_cmdQueue[60] = {0}; 

void main(void) { 

    clean_buffers(); 

    while (1) { 
     ;// MCU tasks   
    } 
} 

void clean_buffers(void) { 
    unsigned char theCount = 0; 
    byte queIdx; 
    for (queIdx = 0; queIdx < 59; queIdx++) { 
     struct DEV_STATUS *p_struct; 
     unsigned char *p_data; 
     p_struct = &g_cmdQueue[queIdx]; 
     p_data = &p_struct->DATA; 
     p_struct->ADDR = 0; 
     p_struct->DEV_HAS_DATA = 0; 
     p_struct->ETH_HAS_DATA = 0; 
     theCount = 0; 
     while(*(p_data+theCount) != 0) { 
      *(p_data+(theCount++)) = 0; 
     } 
    }  
} // EOF main.c 

tôi nhận được một lỗi biên dịch "thành viên struct/đoàn dự kiến" vào dòng sau:

p_data = &p_struct->DATA; 

Làm thế nào tôi nên viết một con trỏ nếu tôi là để truy cập, ví dụ, cụ thể giá trị của cấu trúc thành viên DATA [3]? Tôi bối rối, tôi nghĩ rằng như p_data = & p_struct-> DATA; được xác định, tôi sẽ có thể nhận được nó bằng cách sử dụng * (pdata + 3) nhưng tôi đoán tôi đang thiếu một cái gì đó.

+0

Cảm ơn tất cả các câu trả lời, tôi đánh giá cao nó. – Nate

+1

Thông báo lỗi không có ý nghĩa. Bạn đang sử dụng trình biên dịch nào? – AnT

Trả lời

8

Bạn có chắc là bạn đang biên dịch cùng mã bạn đã đăng ở đây không?

Nếu trình biên dịch của bạn phàn nàn tại dòng

p_data = &p_struct->DATA; 

này với một "thành viên struct/đoàn dự kiến" tin nhắn, trình biên dịch của bạn có lẽ là bị hỏng.

Lưu ý rằng &p_struct->DATA là biểu thức hoàn toàn hợp lệ trong C. Hoàn toàn không có vấn đề gì với biểu thức này.

Vấn đề ở đây chỉ là đây không phải là những gì bạn cần trong trường hợp của bạn. &p_struct->DATA trả về một con trỏ tới toàn bộ mảng 'DATA', tức là một con trỏ thuộc loại unsigned char (*)[20]. Bạn đang cố gán giá trị này cho con trỏ thuộc loại unsigned char *. Điều này là bất hợp pháp trong C, vì các kiểu này hoàn toàn khác nhau, nhưng các trình biên dịch C truyền thống trả lời nó với cảnh báo "loại không khớp" và thực hiện chuyển đổi ngầm (BTW, có nghĩa là mã ban đầu của bạn, mặc dù "bẩn", nên vẫn hoạt động như dự định).

Thậm chí nếu một số trình biên dịch quyết định gắn cờ sự không phù hợp này dưới dạng lỗi (điều này là tốt), nó vẫn không nên khiếu nại về bất kỳ vấn đề nào của loại "struct/union member expected". Không có vấn đề như vậy ở đây.

P.S. Như đã nói, những gì bạn thực sự cần là p_data = &p_struct->DATA[0], nhưng điều đó vẫn không giải thích được hành vi lạ của trình biên dịch của bạn. Nó có thể là 'DATA' là một macro được định nghĩa ở đâu đó trước định nghĩa 'clean_buffers' không?

Đã thêm ngày 10/19/2009: Nate, trong mã của bạn, bạn truy cập mảng bằng cách sử dụng chỉ mục theCount. Vì bạn đang sử dụng truy cập chỉ mục anyway, thực sự không có lý do gì để thậm chí tạo ra con trỏ mà bạn đang cố gắng tạo ra. Mã này sẽ làm việc hoàn toàn tốt đẹp mà không cần bất kỳ con trỏ bổ sung, chỉ acess các DATA lĩnh vực trực tiếp

theCount = 0; 
while (p_struct->DATA[theCount] != 0) { 
    p_struct->DATA[theCount++] = 0; 

(tôi có lẽ muốn sử dụng một chu kỳ for đây).

Nếu bạn thực sự nhấn mạnh vào việc tạo ra con trỏ này và vẫn sử dụng truy cập chỉ mục, mã nên trông giống như sau (những người khác đã gợi ý rằng hơn một lần)

p_data = p_struct->DATA; /* or &p_struct->DATA[0] */ 
... 
theCount = 0; 
while (p_data[theCount] != 0) { 
    p_data[theCount++] = 0; 

Hơn nữa, bạn có thể lựa chọn một nhiều hơn "kỳ lạ" biến thể :)

unsigned char (*p_data)[20]; /* <- note: declared differently */ 
... 
p_data = &p_struct->DATA; /* <- note: your original version */ 
... 
theCount = 0; 
while ((*p_data)[theCount] != 0) { 
    (*p_data)[theCount++] = 0; 

Tuy nhiên, trở về một phiên bản unsigned char *p_data, kể từ khi bạn tạo con trỏ đó, nó có thể có ý nghĩa hơn để sử dụng một "trượt con trỏ" kỹ thuật thay vì sử dụng truy cập chỉ mục

unsigned char *p_data; 
... 
p_data = p_struct->DATA; /* or &p_struct->DATA[0] */ 
... 
while (*p_data != 0) { 
    *p_data++ = 0; 

Như thường lệ, đó là vấn đề sở thích cá nhân. Tất nhiên, không có gì trong số này sẽ làm việc cho đến khi bạn thoát khỏi sự can thiệp từ vĩ mô.

+0

'& p_struct-> DATA' là một con trỏ * tới một mảng char *, không phải là con trỏ * đến một ký tự *. OP muốn sau này. –

+0

@Loadmaster: Đó chính là điều tôi đang nói trong bài đăng của tôi. Bạn đã thực sự đọc nó chưa? Điểm của bài viết của tôi là giải thích áp phích ban đầu những gì mã ban đầu của ông thực sự có nghĩa là. Và để chỉ ra rằng thông báo lỗi là gây hiểu lầm tốt nhất. (Đối với những gì OP muốn - đó là cho OP để quyết định và cho biết.) – AnT

+0

Không thể tin rằng điều này là downvoted. Chính xác những gì tôi nghĩ. Bây giờ tôi không cần thêm câu trả lời nữa :) +1 tất nhiên. (Và thật mỉa mai là câu trả lời được chấp nhận cho thấy ràng buộc sai '(& p_struct) -> DATA' và là +4!) –

3

Thua các & trong p_data = &p_struct->DATA;

p_struct đã là một con trỏ. Sau đó, sử dụng p_data [] để truy cập mảng của bạn.

+0

Cảm ơn bạn, vì bất kỳ lý do gì nó không bao giờ đánh tôi sử dụng p_data [] để truy cập mảng. Tôi tự hỏi nếu dấu và thừa không, cảm ơn cho xác nhận. – Nate

+0

Câu trả lời của bạn cho thấy rằng ràng buộc là '(& p_struct) -> DATA', nhưng đó không phải là trường hợp. –

2

Những gì bạn nên viết là một trong hai điều:

p_data = p_struct->DATA; // DATA is the address of the first element. 

HOẶC

p_data = &p_struct->DATA[0]; // taking the address of the first element. 
1

Đơn giản chỉ cần loại bỏ các & ngay từ đầu, như thế này:

p_data = p_struct->DATA; 

Đó là đặc biệt sintax cho mảng (nhớ chúng được truyền luôn là tham chiếu) và nó tương đương với:

p_data = &p_struct->DATA[0]; 

Và vâng, bây giờ bạn có thể sử dụng * (pdata + 3)

Hy vọng nó giúp.

-1

Rất tiếc! Cảm ơn bạn AndreyT

struct DEV_STATUS * p_struct; unsigned char * p_data; p_struct = & g_cmdQueue [queIdx]; p_data = & p_struct-> DATA;

p_struct là con trỏ đến struct DEV_STATUS.
&p_struct là địa chỉ của con trỏ đến struct DEV_STATUS (hoặc con trỏ đến con trỏ đến struct DEV_STATUS).

Bạn có thể muốn thay đổi dòng để

p_data = p_struct->DATA; 

Oh ... chức năng clean_buffers() của bạn không "sạch" các yếu tố g_cmdQueue[59].

Và, bởi vì nó là đối tượng toàn cục, mảng g_cmdQueue được khởi tạo cho tất cả các số 0 ngay cả trước câu lệnh đầu tiên của main() exceutes.

+0

Không, bạn đi sai kết hợp. '& p_struct-> DATA' là viết tắt của' & (p_struct-> DATA) ', không phải cho' (& p_struct) -> DATA'. Không có con trỏ trỏ tới đây. – AnT

Các vấn đề liên quan