简体   繁体   English

从结构访问数组并将其转换为指针

[英]Accessing an array from a struct and casting it to a pointer

struct message {
  uint8_t start;
  uint16_t length;
  uint8_t data[10];
  uint8_t checkSum;
} __attribute__((packed));

struct message devices[10];

void request(struct message *msg) {
  struct request *req = (struct request *)&msg->data;
  req->operation = 1;
  req->requesterAddress = MASTER_ADDRESS;      
}

request(&devices[0]);

My question is, why the ampersand at "&msg->data" ? 我的问题是,为什么“&msg-> data”中的与号?

My understanding is that the function "request" receives a pointer "msg" to a struct. 我的理解是函数“ request”接收指向结构的指针“ msg”。 msg->data retrieves the pointer "data" from the struct pointed by "msg" ("data" is an array), and it is then casted to another pointer type (struct request *). msg-> data从“ msg”指向的结构中检索指针“ data”(“ data”是一个数组),然后将其强制转换为另一种指针类型(结构请求*)。

So that part should be (struct request *)msg->data; 所以那部分应该是(struct request *)msg-> data; So why the ampersand(&)? 那么,为什么与号(&)?

Well, this code is not C because __attribute__((packed)) is only valid in gcc and some other specific implementation but definitely does not exist in standard C. 嗯,这段代码不是C,因为__attribute__((packed))仅在gcc和其他一些特定实现中有效,但在标准C中绝对不存在。

But provided sizeof(struct message) <= 10 , the rest of the code is correct code according to 4. Conformance but contains unspecied behaviour and may contain undefined behaviour depending of the implementation 但是,如果sizeof(struct message) <= 10 ,则其余代码是根据4. Conformance 正确代码。 4. Conformance但包含未指定的行为,并且根据实现可能包含未定义的行为

  • request(&devices[0]); and void request(struct message *msg) {...} : Ok: request expects a struct message * and receive the address of first element of an array of struct message - all is fine here void request(struct message *msg) {...} :好: request需要一个struct message *并接收struct message数组的第一个元素的地址-一切都很好
  • struct request *req = (struct request *)&msg->data; : that is the most interesting part. :这是最有趣的部分。
    • msg->data is a char array, that is an aggregate. msg->data是一个char数组,它是一个聚合。 The address of an aggregate is the address of its first byte. 聚合的地址是其第一个字节的地址。 Said differently (char *) &msg-> data (address of first byte of the aggregate) is the same as msg->data (array decaying to a pointer to its first element) 表示不同(char *) &msg-> data (聚合的第一个字节的地址)与msg->data (数组衰减到指向其第一个元素的指针)相同
    • (struct request *)&msg->data; the pointer to char is casted to a pointer to struct request . char的指针被强制转换为struct request的指针。 Depending of the implementation, nothing guarantees that the pointer will be correctly aligned. 取决于实现方式,没有任何东西可以保证指针将正确对齐。 If it is not, this is undefined behaviour according to 6.3.2.3 Pointers § 7. If is is, we still have unspecified behaviour according to 6.5 Expressions § 6-7, because the new pointer will be used to store an element that has not the declared type of char[10] . 如果不是,则根据6.3.2.3指针§7,这是未定义的行为。如果是,则根据6.5表达式§6-7,我们仍然具有未指定的行为,因为新的指针将用于存储没有char[10]的声明类型。 But this will be accepted by all known implementation, because internally they process the same char arrays (explicit type) and allocated memory (no declared type) - simply because they need to implement malloc (see Is it possible to write a conformant implementation of malloc in C? ) 但这将为所有已知的实现所接受,因为它们在内部处理相同的char数组(显式类型)和分配的内存(无声明的类型)-仅仅是因为它们需要实现malloc (请参阅是否可以编写一致的malloc实现)在C中?

The rest of the code contains no other problem. 其余代码没有其他问题。 But it should be noticed that if the __attribute__(packed) is honoured by the implementation, the field data will be the third byte of the struct, which gives a weird alignment. 但是需要注意的是,如果__attribute__(packed)被实现支持,则字段data将是该结构的第三个字节,这将产生一个奇怪的对齐方式。 That can lead to crashes on implementation that require strict alignment for certain types. 这可能导致实现崩溃,而这种崩溃要求对某些类型进行严格的调整。


References from n1256 draft for C99 来自C99的n1256草案的参考

  1. Conformance 符合标准
    ... ...
    2 If a ''shall'' or ''shall not'' requirement that appears outside of a constraint is violated, the behavior is undefined... 2如果违反了在约束之外出现的“应”或“不应”要求,则该行为未定义...
    3 A program that is correct in all other aspects , operating on correct data, containing unspecified behavior shall be a correct program ... 3 在所有其他方面都是正确的 ,使用正确数据,包含未指定行为的程序应为正确程序 ...

6.3.2.3 Pointers 6.3.2.3指针
... ...
7 A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. 7指向对象或不完整类型的指针可以转换为指向不同对象或不完整类型的指针。 If the resulting pointer is not correctly aligned for the pointed-to type, the behavior is undefined . 如果结果指针未针对指向类型正确对齐,则该行为为undefined Otherwise, when converted back again, the result shall compare equal to the original pointer. 否则,当再次转换回时,结果应等于原始指针。 When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object . 将指向对象的指针转换为指向字符类型的指针时,结果指向该对象的最低寻址字节

6.5 Expressions 6.5表达式
... ...
6 The effective type of an object for an access to its stored value is the declared type of the object, if any. 6对象访问其存储值的有效类型是该对象的声明类型(如果有)。 If a value is stored into an object having no declared type through an lvalue having a type that is not a character type, then the type of the lvalue becomes the effective type of the object for that access and for subsequent accesses that do not modify the stored value. 如果通过具有非字符类型的左值将值存储到没有声明类型的对象中,则该左值的类型将成为该访问和不修改该访问的后续访问的对象的有效类型。储值。 If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is copied, if it has one. 如果使用memcpy或memmove将值复制到没有声明类型的对象中,或者将其复制为字符类型数组,则用于该访问以及不修改该值的后续访问的修改对象的有效类型为从值复制对象的有效类型(如果有)。 For all other accesses to an object having no declared type, the effective type of the object is simply the type of the lvalue used for the access. 对于没有声明类型的对象的所有其他访问,该对象的有效类型只是用于访问的左值的类型。

7 An object shall have its stored value accessed only by an lvalue expression that has one of the following types: 7对象应仅通过具有以下类型之一的左值表达式访问其存储值:

  • atype compatible with the effective type of the object, 与对象的有效类型兼容的类型,
  • aqualified 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