2014-10-17 3 views
5

Я изучаю C и задаюсь вопросом о структурах.Копировать структуру в массив символов

У меня есть

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

Это должно занять по крайней мере 30 байт памяти для хранения. Можно ли скопировать все эти данные в переменную char foo[30]? Какой будет синтаксис?

+1

Непонятно, но вы можете попробовать memcpy (* dest, * src, sizeof (src)); –

+4

Если вы обнаружите, что говорите такие вещи, как «очевидно», вы должны немедленно поднять несколько красных флагов. –

+0

@KerrekSB хорошо не занимает 30 байт? Я знаю, что для более сложных тем я должен быть более осторожным. – yiwei

ответ

10

Вы не можете просто скопировать непосредственно все это, потому что компилятор может произвольно решать, как колодки/упаковать эту структуру. Вам понадобятся три memcpy звонки:

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

Это правильно, если семантика массивов 'char' - это сырые байты. Если они NUL завершают строки, необходимо другое решение (например, [ответ Triton Man] (http://stackoverflow.com/a/26430537/1392132)). Из вопроса неясно, что это такое. – 5gon12eder

+0

Эта техника называется «сериализация»? (не будет ли проблем с заполнением?) – ryyker

+0

Вместо того, чтобы вручную вычислять смещения каждого поля в структуре, вам лучше использовать макрос для этого. – Sparky

0

вы могли бы сделать следующее, если у вас есть переменная MyStruct с именем улица:

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

Не будет работать, если массивы не имеют нулевой конец или если они короче, чем описано. –

+0

Да, это связано с предположением, что они являются строками. –

+0

плюс никогда не использовать strcpy. : P Всегда используйте strncpy. –

3

Размер struct myStruct является sizeof(struct myStruct) и больше ничего. Это будет не менее 30, но это может быть любое большее значение.

Вы можете сделать это:

char foo[sizeof(struct myStruct)]; 

struct myStruct x; /* populate */ 

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

Проблема printf («% s», foo) будет отображать только первый массив символов, предполагая, что они являются строками с нулевым завершением. –

+0

Вы можете использовать offsetof(), чтобы получить строки, которые не находятся в первой позиции. – 2501

1

Согласно стандарту C (6.2.6 Представления типов)

4 Значения сохраняются в небитового поля объектов любого другого типа объекта состоят из бит n × CHAR_BIT, где n - размер объекта этого типа , в байтах. Значение может быть скопировано в объект типа unsigned char [n] (например, от memcpy); результирующий набор байтов называется представлением объекта значения.

Таким образом, вы можете просто написать

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

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

Примите во внимание, что вы можете копировать элементы данных раздельно в одном массиве. Например

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

Хотя это действительно C, он не обязательно будет делать то, что хочет OP. – 5gon12eder

+0

@ 5gon12eder Я не понял, что вы хотите сказать. В любом случае я - ОП, который решает, что он ждет. –

+0

Я предполагаю, что он действительно хочет 'foo = s.member1 + s.mamber2 + s.member3', так как мы будем писать его в Python, где' + 'выполняет конкатенацию списка. Ваше решение будет копировать байты объекта, как вы хорошо объясните в ответе. – 5gon12eder

0

Pretty simple with memcpy.

char foo[30]; 
struct myStruct s; 

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

memcpy(foo, &s, 30); 
0

Да, это возможно.

Есть несколько способов, которыми вы можете это сделать. Ниже приведены два самых простых метода.

struct myStruct myVar; 

/* Initialize myVar */ 
... 

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

Или, если вы имеете дело с указателем ...

struct myStruct * myVarPtr; 

/* Initialize myVarPtr */ 
... 

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

Обратите внимание, что при копировании структуры в/из массива символов, как это, вы должны быть очень осторожны, так как структура размеры не всегда то, что вы могли бы сначала подумать. В вашем конкретном случае не может быть никаких проблем; но в целом вы должны, по крайней мере, знать о возможных проблемах заполнения, выравнивания и размера шрифта, которые могут изменить размер вашей структуры.

Надеюсь, это поможет.

Смежные вопросы