Why does casting a struct address to an int pointer, dereferencing, and using that as the LVALUE in a statement crash my microcontroller?

StackOverflow https://stackoverflow.com/questions/18620476

The following code crashes my microprocessor at runtime.

struct dummytype dummy;
struct crummytype crummy;
*(unsigned int*)&dummy = *(unsigned int*)&crummy;

Assuming both structs are the same size, is there something about this code that is not valid C? Is its validity contingent on anything particular?

有帮助吗?

解决方案

This is only valid if both structures have an unsigned int as the first member.

C99 §6.7.2.1/13

Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.

Putting that simply, given an address of a structure object, you can cast that address to a pointer-to-first-member-type:

struct A
{
    unsigned int n;
    char junk[5];
};

struct A a;
unsigned int *p = (unsigned int *)&a;  // OK. pointer is proper for first member type
unsigned long*x = (unsigned long *)&a; // BAD

In short, your code is only legitimate if both structure types have an unsigned int for their first member. Anything else is undefined behavior (void * not withstanding, but since it is non-dereferencable, it really isn't applicable here). Each structure type being "big enough" to hold an unsigned int isn't enough. Their first member must actually be an unsigned int.

其他提示

Even through both structures have same size, overlapping behavior is undefined.

if the structures are like this ,above statement will gives result what you are looking.

struct dummytype
{
int a;
};
struct crummytype
{
int b;
};    

if the structures are like this ,you can't say what would be the result.

struct dummytype
{
char name[20];
int a;
};
struct crummytype
{
char name1[20];
int b;
};

It's invalid C by both the alignment requirements of int and the aliasing rules (accessing an object via an lvalue of type different from the effective type of the object).

C99 draft standard states (Annex J):

J.2 Undefined behavior

The behavior is undefined in the following circumstances:

[...] An object is assigned to an inexactly overlapping object or to an exactly overlapping object with incompatible type (6.5.16.1).

then, for what concerns compatible types:

6.2.7 Compatible type and composite type

Two types have compatible type if their types are the same. Additional rules for determining whether two types are compatible are described in 6.7.2 for type specifiers, in 6.7.3 for type qualifiers, and in 6.7.5 for declarators. Moreover, two structure, union, or enumerated types declared in separate translation units are compatible if their tags and members satisfy the following requirements: If one is declared with a tag, the other shall be declared with the same tag. If both are complete types, then the following additional requirements apply: there shall be a one-to-one correspondence between their members such that each pair of corresponding members are declared with compatible types, and such that if one member of a corresponding pair is declared with a name, the other member is declared with the same name. For two structures, corresponding members shall be declared in the same order. For two structures or unions, corresponding bit-fields shall have the same widths. For two enumerations, corresponding members shall have the same values.

making the two structs the same size is not sufficient to make them compatible types, so the behavior is undefined.

Edit: for sake of completeness I add the excerpt cited by @PascalCuoq in a comment to another answer in this thread, which is also relevant:

6.5 Expressions

[...]

7

An object shall have its stored value accessed only by an lvalue expression that has one of the following types:

  • a type compatible with the effective type of the object,
  • a qualified version of a type compatible with the effective type of the object,
  • a type that is the signed or unsigned type corresponding to the effective type of the object,
  • a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
  • an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
  • a character type.
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top