简体   繁体   English

将数组强制转换为以一个数组为成员的结构是否安全?

[英]Is it safe to cast an array to a struct with one array as member?

In the following setup在以下设置中

typedef struct {
    unsigned char data[64];
} mystruct;

int myfunc(mystruct* arg); // fills arg with data

is it safe to call myfunc with a pointer to a 64 byte array?使用指向 64 字节数组的指针调用myfunc是否安全 Eg例如

unsigned char buffer[64];
myfunc((mystruct*) buffer)

In my concrete application I am using a JNI direct ByteBuffer which should be filled from myfunc .在我的具体应用程序中,我使用的是 JNI 直接 ByteBuffer ,它应该从myfunc填充。

unsigned char* dbbuffer = (unsigned char*) (*env)->GetDirectBufferAddress(env, jbuffer);

If the cast is not safe, I would have to create a mystruct , call myfunc and then memcopy to dbbuffer , which I would like to avoid.如果转换不安全,我将不得不创建一个mystruct ,调用myfunc然后memcopydbbuffer ,我想避免这种情况。

Technically it works and you can use it.从技术上讲,它有效,您可以使用它。 As pointed in comments the relevant part of the ANSI standard is:正如评论中指出的,ANSI 标准的相关部分是:

6.7.2.1: Structure and union specifiers 6.7.2.1:结构和联合说明符

... 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.结构对象内可能有未命名的填充,但不是在其开头。

The strict aliasing does not matter in this case.在这种情况下,严格别名无关紧要。 Strict aliasing rule specifies in which circumstances a value of some type can be changed by changing a value of another type.严格别名规则指定在何种情况下可以通过更改另一种类型的值来更改某种类型的值。 The main interest of this rule are scalar types like int and float .此规则的主要兴趣是标量类型,如intfloat In your particular case it is evident that by changing a member of a struct ( unsigned char [] ) you change the whole structure and vice versa.在您的特定情况下,很明显,通过更改结构( unsigned char [] )的成员,您可以更改整个结构,反之亦然。

This case is covered by the 5th subcase of the strict aliasing rule.这种情况包含在严格别名规则的第 5 个子情况中。 I quote the whole part for the sake of completeness:为了完整起见,我引用了整个部分:

6.5 Expressions, p.7 6.5 表达式,第 7 页

An object shall have its stored value accessed only by an lvalue expression that has one of the following types (The intent of this list is to specify those circumstances in which an object may or may not be aliased):对象只能通过具有以下类型之一的左值表达式访问其存储值(此列表的目的是指定对象可以或不可以别名的情况):

— 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 — 一种字符类型

where the definition of aggegate types is in:其中聚合类型的定义在:

6.2.5 Types, p.21 6.2.5 类型,第 21 页

Arithmetic types and pointer types are collectively called scalar types.算术类型和指针类型统称为标量类型。 Array and structure types are collectively called aggregate types.数组和结构类型统称为聚合类型。

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

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