10

I am learning C and have a question about structs.

I have a

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

This should take at least 30 bytes of memory to store. Would it be possible to copy all of this data into the variable char foo[30]? What would be the syntax?

5
  • 1
    Not positive, but you could try memcpy(*dest, *src, sizeof(src)); Commented Oct 17, 2014 at 17:37
  • 4
    If you find yourself saying things like "obviously", you should immediately raise multiple red flags. Commented Oct 17, 2014 at 17:41
  • @KerrekSB well doesn't it take 30 bytes? I know that for more complicated topics I should be more wary Commented Oct 17, 2014 at 17:42
  • 1
    @YiweiG: The thing is, you don't confidently know for sure. So nothing should be "obvious" unless you can actually back that up. Rubber-duck it, with standard references at hand, then we can talk about "obvious". Commented Oct 17, 2014 at 17:43
  • @KerrekSB fair enough. I've edited the post for clarification Commented Oct 17, 2014 at 17:43

6 Answers 6

19

You can't just directly copy the whole thing, because the compiler may arbitrarily decide how to pad/pack this structure. You'll need three memcpy calls:

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);
Sign up to request clarification or add additional context in comments.

5 Comments

This is correct if the semantics of the char arrays is raw bytes. If they are NUL terminates strings, another solution (such as Triton Man's answer) is needed. It is not clear from the question what it is.
Is this technique referred to as serializing? (will it avoid padding problems?)
Instead of manually calculating the offsets of each field in the structure, you would be better off using a macro to do this.
Instead of foo + sizeof s.member1 can I do &foo[16]?
Yes, that's fine. I just used the sizeof for ease of maintenance.
5

The size of struct myStruct is sizeof(struct myStruct) and nothing else. It'll be at least 30, but it could be any larger value.

You can do this:

char foo[sizeof(struct myStruct)];

struct myStruct x; /* populate */

memcpy(foo, &x, sizeof x);

3 Comments

problem is printf("%s", foo) will only display the first char array, assuming they are null terminated strings.
You can use offsetof() to get strings that are not in the first position.
Will this still work if the members of the struct are not char but lets say a bunch of ints or a mix of ints and char?
4

According to the C Standard (6.2.6 Representations of types)

4 Values stored in non-bit-field objects of any other object type consist of n × CHAR_BIT bits, where n is the size of an object of that type, in bytes. The value may be copied into an object of type unsigned char [n] (e.g., by memcpy); the resulting set of bytes is called the object representation of the value.

So you can write simply

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

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

Take into account that you could copy the data members separatly in one array. For example

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 ) );

3 Comments

While this is valid C, it won't necessarily do what the OP wants.
@5gon12eder I have not understood what you want to say. In any case iy is OP that decides what he wnats.
My guess is that he actually wants foo = s.member1 + s.mamber2 + s.member3, as we would write it in Python where + performs list concatenation. Your solution will copy the bytes of the object, as you explain pretty well in the answer.
1

Yes, it is possible.

There are different ways you can go about doing this. Below are the two simplest methods.

struct myStruct  myVar;

/* Initialize myVar */
...

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

Or if you are dealing with a pointer ...

struct myStruct *  myVarPtr;

/* Initialize myVarPtr */
...

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

Note that when copying a structure to/from a character array like this, you have to be very careful as structure sizes are not always what you might first think. In your particular case, there might not be any issues; but in general, you should at least be aware of potential padding, alignment and type size issues that may change the size of your structure.

Hope this helps.

Comments

0

you could do the following if you have a myStruct variable named st:

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

4 Comments

Won't work if the arrays aren't null terminated or if they are shorter than described.
yes, this goes with the assumption that they are strings.
plus never use strcpy. :P Always use strncpy.
To get rid of the ambiguity (for this answer only) spec. that you are assuming null terminated strings. (I know the OP does not specify)
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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.