繁体   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?

以下代码在运行时崩溃了我的微处理器。

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

假设两个结构都是相同的大小,这个代码是否有一些无效的C? 它的有效性是否取决于任何特定的?

这仅在两个结构都具有unsigned int作为第一个成员时才有效。

C99§6.7.2.1/ 13

在结构对象中,非位字段成员和位字段所在的单元具有按声明顺序增加的地址。 指向适当转换的结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然。 结构对象中可能存在未命名的填充,但不是在其开头。

简单地说,给定一个结构对象的地址,您可以将该地址转换为指向第一个成员类型的指针:

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

简而言之,如果两个结构类型的第一个成员都具有unsigned int ,那么您的代码才是合法的。 其他任何东西都是未定义的行为( void *不能承受,但因为它是不可解除引用的,所以这里真的不适用)。 每个结构类型“足够大”以容纳unsigned int是不够的。 他们的第一个成员实际上必须unsigned int

即使两个结构具有相同的大小,重叠行为也是不确定的。

如果结构是这样的,上面的陈述将给出你正在寻找的结果。

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

如果结构是这样的,你不能说结果会是什么。

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

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

C99标准草案(附件J):

J.2未定义的行为

在以下情况下,行为未定义:

[...]将对象分配给不完全重叠的对象或具有不兼容类型的完全重叠的对象(6.5.16.1)。

然后,关于兼容类型:

6.2.7兼容型和复合型

如果类型相同,则两种类型具有兼容类型。 用于确定两种类型是否兼容的附加规则在6.7.2中描述了类型说明符,在6.7.3中描述了类型限定符,在6.7.5中描述了声明符。 此外,如果它们的标记和成员满足以下要求,则在单独的转换单元中声明的两个结构,联合或枚举类型是兼容的:如果使用标记声明一个,则另一个应使用相同的标记声明。 如果两者都是完整类型,则以下附加要求适用:其成员之间应存在一对一的对应关系,使得每对相应成员都声明为具有兼容类型,并且如果相应对的一个成员是使用名称声明,另一个成员使用相同的名称声明。 对于两个结构,相应的成员应按相同的顺序声明。 对于两个结构或联合,相应的位域应具有相同的宽度。 对于两个枚举,相应的成员应具有相同的值。

使两个结构体具有相同的大小并不足以使它们成为兼容类型,因此行为是不确定的。

编辑:为了完整起见,我将@PascalCuoq引用的摘录添加到此帖子中的另一个答案的注释中,这也是相关的:

6.5表达式

[...]

7

对象的存储值只能由具有以下类型之一的左值表达式访问:

  • 与对象的有效类型兼容的类型,
  • 与对象的有效类型兼容的类型的限定版本,
  • 与对象的有效类型对应的有符号或无符号类型的类型,
  • 与有效类型的对象的限定版本对应的有符号或无符号类型的类型,
  • 聚合或联合类型,包括其成员中的上述类型之一(包括递归地,子聚合或包含联合的成员),或者
  • 一个字符类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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