在以下设置中
typedef struct {
unsigned char data[64];
} mystruct;
int myfunc(mystruct* arg); // fills arg with data
使用指向64字节数组的指针调用myfunc
是否安全?例如。
unsigned char buffer[64];
myfunc((mystruct*) buffer)
在我的具体应用程序中,我使用的是JNI直接ByteBuffer,应该从myfunc
填充。
unsigned char* dbbuffer = (unsigned char*) (*env)->GetDirectBufferAddress(env, jbuffer);
如果演员不安全,我将不得不创建一个mystruct
,调用myfunc
然后memcopy
到dbbuffer
,我想避免。
从技术上讲,它可以工作,你可以使用它。正如评论中所指出的,ANSI标准的相关部分是:
6.7.2.1:结构和联合说明符
...指向适当转换的结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然。结构对象中可能存在未命名的填充,但不是在其开头。
在这种情况下,严格的混叠无关紧要。严格别名规则指定在哪种情况下可以通过更改另一种类型的值来更改某种类型的值。这条规则的主要兴趣是像int
和float
这样的标量类型。在您的特定情况下,很明显,通过更改结构的成员(unsigned char []
),您可以更改整个结构,反之亦然。
此案例由严格别名规则的第5个子案例涵盖。为了完整起见,我引用整个部分:
6.5表达式,第7页
对象的存储值只能由具有以下类型之一的左值表达式访问(此列表的目的是指定对象可能或可能没有别名的情况):
- 与对象的有效类型兼容的类型,
- 与对象的有效类型兼容的类型的限定版本,
- 对应于对象的有效类型的有符号或无符号类型的类型,
- 对应于对象有效类型的限定版本的有符号或无符号类型,
- 聚合或联合类型,其成员中包含上述类型之一(包括递归地,子聚合或包含联合的成员),或者
- 角色类型
聚合类型的定义在:
6.2.5类型,第21页
算术类型和指针类型统称为标量类型。数组和结构类型统称为聚合类型。