我有一个名为Characters
的结构,一个名为a
的结构的变量,以及一个名为pChar
的char的指针,我想更改FirstChar
的值在a到27到pChar
struct Characters {
short CharCount;
char FirstChar;
char SecondChar;
char ThirdChar;
};
struct Characters a = {3, 4, 5, 6};
char* pChar;
pChar = (char*)&a;
*(pChar+2) = 27;
我可以安全地将结构a转换为char*
吗?并且填充是否会添加到结构的末尾?如果我使用*(pChar+2)
,我会保证它会引用FirstChar
吗?
答案 0 :(得分:6)
我可以安全地将struct a转换为char *吗?
演员本身是安全的。访问指针*(pChar+2) = 27;
的内容并不安全。正式地,它可能会调用未定义的行为,因为它违反了aliasing。
(就使用别名规则而言,使用char *是正常的,但是当将值27写入随机字节时,正式无法保证结果将是什么。并且您可能正在写入填充字节。)
填充是否会添加到结构的末尾?
填充可以添加到结构中的任何位置,除了最开始。
在实践中,做这样的事情可能相当安全,即使不推荐和正式未定义的行为。我还没有遇到一个系统,它不会安全和确定地工作。但你必须确保没有填充:
struct Numbers {
short CharCount;
char FirstChar;
char SecondChar;
char ThirdChar;
};
static_assert(sizeof(struct Numbers) ==
sizeof(short) +
sizeof(char) +
sizeof(char) +
sizeof(char),
"Padding found");
要实际禁用填充,通常会有一些非标准方法,例如#pragma pack(1)
。
修改强>
可靠地获取结构成员地址的最佳和最便携的方法可能是:
#include <stddef.h>
struct Numbers x;
char* ptr = (char*)&x + offsetof(struct Numbers, FirstChar);
答案 1 :(得分:2)
你可以将任何指针类型转换为另一种指针类型,并且仍然应该指向相同的内存空间,如果这就是你所要求的。
然而,如果你按照你的方式修改结构中的变量,很难确定会发生什么,主要是因为memory alignment。
您可以通过设置#pragma pack(1)
来抑制大多数编译器中的内存对齐。
如果你这样做,char
长1个字节而short
长2个字节(可能并不总是),只有这样才能保证修改pChar[2]
会改变价值FirstNum
。