你可以将struct指针转换为char指针吗?

时间:2015-05-27 06:21:07

标签: c

我有一个名为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吗?

2 个答案:

答案 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