简体   繁体   English

为什么将结构地址转换为int指针,解除引用,并将其用作语句中的LVALUE会使我的微控制器崩溃?

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

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? 假设两个结构都是相同的大小,这个代码是否有一些无效的C? Is its validity contingent on anything particular? 它的有效性是否取决于任何特定的?

This is only valid if both structures have an unsigned int as the first member. 这仅在两个结构都具有unsigned int作为第一个成员时才有效。

C99 §6.7.2.1/13 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. 简而言之,如果两个结构类型的第一个成员都具有unsigned int ,那么您的代码才是合法的。 Anything else is undefined behavior ( void * not withstanding, but since it is non-dereferencable, it really isn't applicable here). 其他任何东西都是未定义的行为( void *不能承受,但因为它是不可解除引用的,所以这里真的不适用)。 Each structure type being "big enough" to hold an unsigned int isn't enough. 每个结构类型“足够大”以容纳unsigned int是不够的。 Their first member must actually be an unsigned int . 他们的第一个成员实际上必须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;
};

通过int的对齐要求和别名规则(通过与对象的有效类型不同的类型的左值访问对象),它是无效的C.

C99 draft standard states (Annex J): C99标准草案(附件J):

J.2 Undefined behavior J.2未定义的行为

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). [...]将对象分配给不完全重叠的对象或具有不兼容类型的完全重叠的对象(6.5.16.1)。

then, for what concerns compatible types: 然后,关于兼容类型:

6.2.7 Compatible type and composite type 6.2.7兼容型和复合型

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. 用于确定两种类型是否兼容的附加规则在6.7.2中描述了类型说明符,在6.7.3中描述了类型限定符,在6.7.5中描述了声明符。 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: 编辑:为了完整起见,我将@PascalCuoq引用的摘录添加到此帖子中的另一个答案的注释中,这也是相关的:

6.5 Expressions 6.5表达式

[...] [...]

7 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 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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