2014-10-17 34 views
5

Tôi đang học C và có câu hỏi về cấu trúc.Sao chép cấu trúc vào mảng char

Tôi có một

struct myStruct { 
    char member1[16]; 
    char member2[10]; 
    char member3[4]; 
}; 

này nên phải mất ít nhất 30 byte của bộ nhớ để lưu trữ. Có thể sao chép tất cả dữ liệu này vào biến số char foo[30] không? Cú pháp sẽ là gì?

+1

Không tích cực, nhưng bạn có thể thử memcpy (* dest, * src, sizeof (src)); –

+4

Nếu bạn thấy mình nói những thứ như "rõ ràng", bạn nên ngay lập tức nâng cao nhiều cờ đỏ. –

+0

@KerrekSB cũng không mất 30 byte? Tôi biết rằng đối với các chủ đề phức tạp hơn tôi nên cảnh giác hơn – yiwei

Trả lời

10

Bạn có thể không chỉ là sao chép trực tiếp toàn bộ điều, bởi vì trình biên dịch tùy tiện có thể quyết định làm thế nào để pad/gói cấu trúc này. Bạn sẽ cần ba memcpy cuộc gọi:

struct myStruct s; 
// initialize s 
memcpy(foo,          s.member1, sizeof s.member1); 
memcpy(foo + sizeof s.member1,     s.member2, sizeof s.member2); 
memcpy(foo + sizeof s.member1 + sizeof s.member2, s.member3, sizeof s.member3); 
+0

Điều này đúng nếu ngữ nghĩa của mảng 'char' là byte thô. Nếu chúng là NUL chấm dứt chuỗi, một giải pháp khác (như câu trả lời của Triton Man] (http://stackoverflow.com/a/26430537/1392132)) là cần thiết. Nó không phải là rõ ràng từ câu hỏi nó là gì. – 5gon12eder

+0

Kỹ thuật này có được gọi là 'serializing' không? (nó sẽ tránh các vấn đề đệm?) – ryyker

+0

Thay vì tính toán thủ công các khoảng trống của từng trường trong cấu trúc, bạn nên sử dụng macro để thực hiện việc này. – Sparky

0

bạn có thể làm như sau nếu bạn có một biến mystruct tên st:

strcpy(foo, st.member1); 
strcat(foo, st.member2); 
strcat(foo, st.member3); 
+2

Sẽ không hoạt động nếu các mảng không bị chấm dứt hoặc nếu chúng ngắn hơn mô tả. –

+0

có, điều này đi với giả định rằng chúng là các chuỗi. –

+0

plus không bao giờ sử dụng strcpy. : P Luôn sử dụng strncpy. –

3

Kích thước của struct myStructsizeof(struct myStruct) và không có gì khác. Nó sẽ có ít nhất 30, nhưng nó có thể là bất kỳ giá trị lớn hơn.

Bạn có thể làm điều này:

char foo[sizeof(struct myStruct)]; 

struct myStruct x; /* populate */ 

memcpy(foo, &x, sizeof x); 
+0

vấn đề là printf ("% s", foo) sẽ chỉ hiển thị mảng char đầu tiên, giả sử chúng là các chuỗi bị vô hiệu. –

+0

Bạn có thể sử dụng offsetof() để nhận các chuỗi không ở vị trí đầu tiên. – 2501

1

Theo tiêu chuẩn C (6.2.6 Đại diện của các loại)

4 Các giá trị được lưu trữ trong các đối tượng phi bit trường của bất kỳ loại đối tượng khác bao gồm n × CHAR_BIT bit, trong đó n là kích thước của một đối tượng thuộc loại , tính bằng byte. Giá trị có thể được sao chép vào một đối tượng thuộc loại char chưa được ký [n] (ví dụ: bởi memcpy); tập hợp các byte kết quả là được gọi là biểu diễn đối tượng của giá trị.

Vì vậy, bạn có thể viết đơn giản

unsigned char foo[sizeof(struct myStruct)]; 
struct myStruct s = { /*...*/ }; 

memcpy(foo, &s, sizeof(struct myStruct)); 

Đi vào tài khoản mà bạn có thể sao chép các thành viên dữ liệu separatly trong một mảng. Ví dụ:

unsigned char foo[30]; 
struct myStruct s = { /*...*/ }; 

unsigned char *p = foo; 
memcpy(p, s.member1, sizeof(s.member1)); 
memcpy(p += sizeof(s.member1), s.member2, sizeof(s.member2)); 
memcpy(p += sizeof(s.member2), s.member3, sizeof(s.member3)); 
+0

Trong khi điều này là hợp lệ C, nó sẽ không nhất thiết phải làm những gì OP muốn. – 5gon12eder

+0

@ 5gon12eder Tôi chưa hiểu bạn muốn nói gì. Trong mọi trường hợp, iy là OP quyết định những gì anh ta muốn. –

+0

Đoán của tôi là anh ta thực sự muốn 'foo = s.member1 + s.mamber2 + s.member3', như chúng ta sẽ viết nó trong Python, nơi' + 'thực hiện kết nối danh sách. Giải pháp của bạn sẽ sao chép các byte của đối tượng, khi bạn giải thích khá tốt trong câu trả lời. – 5gon12eder

0

Khá đơn giản với memcpy.

char foo[30]; 
struct myStruct s; 

s.member1 = //some data 
s.member2 = //some data 
s.member3 = //some data 

memcpy(foo, &s, 30); 
0

Có, có thể.

Có nhiều cách khác nhau để bạn có thể thực hiện việc này. Dưới đây là hai phương pháp đơn giản nhất.

struct myStruct myVar; 

/* Initialize myVar */ 
... 

memcpy (foo, &myVar, sizeof (myStruct)); 

Hoặc nếu bạn đang đối phó với một con trỏ ...

struct myStruct * myVarPtr; 

/* Initialize myVarPtr */ 
... 

memcpy (foo, myVarPtr, sizeof (myStruct)); 

Lưu ý rằng khi sao chép một cấu trúc đến/từ một mảng nhân vật như thế này, bạn phải rất cẩn thận như kích thước cấu trúc là không phải lúc nào cũng là điều đầu tiên bạn nghĩ. Trong trường hợp cụ thể của bạn, có thể không có bất kỳ vấn đề nào; nhưng nói chung, bạn nên ít nhất là nhận thức được các vấn đề về padding, alignment và type có thể thay đổi kích thước của cấu trúc của bạn.

Hy vọng điều này sẽ hữu ích.

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