简体   繁体   English

您可以将结构指针转换为字符指针吗?

[英]Can you cast struct pointer to char pointer?

I have a struct named Characters , a variable of that struct named a , and a pointer to char named pChar and I want to change the value of FirstChar in a to 27 through pChar我有一个名为结构Characters ,即结构命名的变量a ,和一个指向名为焦pChar和我想的值更改FirstChar通过在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;

Can I cast the struct a to char* safely?我可以安全地将 struct a 转换为char*吗? And will the padding be added to the end of the struct?填充是否会添加到结构的末尾? If I used *(pChar+2) will I be guaranteed that it will be referring to FirstChar ?如果我使用*(pChar+2)我能保证它指的是FirstChar吗?

Can I safely cast the struct a to char* safely?我可以安全地将 struct a 转换为 char* 吗?

The cast itself is safe.演员本身是安全的。 Accessing the contents of the pointer *(pChar+2) = 27;访问指针的内容*(pChar+2) = 27; is not safe.不安全。 Formally it may invoke undefined behavior because it violates aliasing .正式它可能会调用未定义的行为,因为它违反了aliasing

(Using char* is fine as far as the aliasing rules are concerned, but when writing the value 27 to a random byte, there are formally no guarantees of what the result will be. And you might be writing to a padding byte.) (就别名规则而言,使用 char* 很好,但是当将值 27 写入随机字节时,正式无法保证结果会是什么。而且您可能正在写入填充字节。)

And will the padding be added to the end of the struct?填充是否会添加到结构的末尾?

Padding may be added anywhere in the struct, except at the very beginning.填充可以添加到结构中的任何地方,除了最开始的地方。


In practice, doing things like this is likely rather safe, even though it is not recommended and formally undefined behavior.在实践中,做这样的事情可能是相当安全的,即使这是不推荐的和正式未定义的行为。 I have yet to encounter a system where it wouldn't work safely and deterministically.我还没有遇到过不能安全和确定地工作的系统。 But you have to ensure that there is no padding:但是你必须确保没有填充:

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");

To actually disable padding there is usually some non-standard way such as #pragma pack(1) .要实际禁用填充,通常有一些非标准方式,例如#pragma pack(1)

EDIT编辑

The best and most portable way to reliably get the address of a struct member might be this:可靠地获取结构成员地址的最佳和最便携的方法可能是这样的:

#include <stddef.h>

struct Numbers x;
char* ptr = (char*)&x + offsetof(struct Numbers, FirstChar);

You can cast any pointer type into another pointer type and should still work in the sense that it points to the same memory space, if thats what you are asking.您可以将任何指针类型转换为另一种指针类型,并且在它指向相同内存空间的意义上仍然可以工作,如果这就是您的要求。

However, its hard to determine whats going to happen if you modify a variable in the structure the way you are doing, mainly because of memory alignment .但是,如果您按照自己的方式修改结构中的变量,则很难确定会发生什么,主要是因为内存对齐

You can suppress memory alignment in most compilers by setting #pragma pack(1) .您可以通过设置#pragma pack(1)在大多数编译器中抑制内存对齐。

If you do so, and char is 1 byte long and short is 2 bytes long (it might not always be), only then its guaranteed that modifying pChar[2] will change the value of FirstChar .如果你这样做,并且char是 1 字节长, short是 2 字节长(它可能并不总是这样),只有这样才能保证修改pChar[2]会改变FirstChar的值。

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

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