简体   繁体   中英

Assigning to an array by casting to a struct

Why does the following code work?

#include <stdio.h>
#define LEN 12

typedef struct
{
    char buffer[LEN];
} string;

int main()
{
    char buffer1[LEN] = "Hello World";
    char buffer2[LEN];

    *(string*)buffer2 = *(string*)buffer1;

    printf("%s",buffer2);
    return 0;
}

As far as I understand, I cannot assign one array to another.

C permits assigning one struct to another of the same type, and the semantics of doing so are defined in terms of the struct representation, as opposed to a member-by-member copy. That a struct representation encompasses the representation of an array does not mean that assigning the value of a struct that contains an array to another struct violates C's prohibition against assigning one array to another.

C furthermore guarantees that the address of the first member of a struct is the same as the address of the struct itself, and it permits object pointers to be cast among different pointer types. In that case, the result of such a conversion is not guaranteed to be correctly aligned, and if it is not then dereferencing that result produces undefined behavior.

On the other hand, the compiler is free to include trailing padding in struct representations. Oftentimes that is done for alignment purposes. If your compiler does that for your struct -- which it likely will do if it applies a 64-bit or greater alignment requirement to it -- then your assignment produces undefined behavior. In that case, if it appears to work then that's because you got lucky.

If, however, it turns out that neither of the above sources of undefined behavior applies, then it is indeed reasonable to expect the code to work as expected. Inasmuch as it is tricky to predict whether that will be the case, however, you would be well advised to avoid code like this.

A better question might be why C disallows array copying. There are likely several reasons, but I think the deepest one is simply for consistency. In almost all contexts, when an an expression or sub-expression evaluates to an array, that value decays to a pointer to the first array element. That includes the subexpressions constituting the operands to an = operator. So in normal C expressions, an array assignment would actually be a pointer assignment, and one that did not have the intended semantics. One would have had to carefully craft an appropriate special case for that situation in order to allow for array assignment.

As pointed out in the comments you are not assigning an array to another but you are assigning a struct to another by means of the cast. Assigning a struct result in copying all the elements (in case of a simple struct, see this post ). The code however it's really bad and you can break it by simply adding another field to the struct.

From your comment "As far as I understand, I cannot assign one array to another." it seems that you created the struct to circumvent the inability to copy one string to another by casting your buffers to the struct in assignment.

This happened to work this time, but it won't always work; structs often have padding and alignment bits between fields.

If you want to copy one string to another in C, use the strcpy or strncpy functions (or, in the case of wchar_t type strings, wcscpy and wcsncpy ).

If you want to copy one array of an arbitrary type to another, use a for loop where you copy each index one by one, or the memcpy function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM