将struct *转换为int *以便能够写入第一个字段

时间:2016-07-16 19:09:17

标签: c struct casting

我最近找到了这个页面:

Making PyObject_HEAD conform to standard C

我对这段话感到好奇:

  

标准C对其精确设计的别名规则有一个特定的例外,以支持Python的情况:也可以通过指向第一个字段的指针访问结构类型的值。例如。 如果struct以int开头,struct *也可以强制转换为int *,允许将int值写入第一个字段

所以我编写了这段代码来检查我的编译器:

struct with_int {
    int a;
    char b;
};

int main(void)
{
    struct with_int *i = malloc(sizeof(struct with_int));
    i->a = 5;
    ((int *)&i)->a = 8;
}

但我得到了error: request for member 'a' in something not a struct or union

我上面的段落是否合适?如果不是,我做错了什么? 另外,如果有人知道C标准在哪里引用此规则,请在此处指出。感谢。

3 个答案:

答案 0 :(得分:5)

您的解释 1 是正确的,但代码不是。

指针i已指向对象,因此指向第一个元素,因此您只需将其强制转换为正确的类型:

int* n = ( int* )i;

然后你只需取消引用它:

*n = 345;

或者一步到位:

*( int* )i = 345;

1 (引用自:ISO:IEC 9899:201X 6.7.2.1结构和联合说明符15)
在结构对象内,非位字段成员和位域中的单位 驻留的地址按声明的顺序增加。指向a的指针 结构对象,适当转换,指向其初始成员(或者如果该成员是a 位字段,然后到它所在的单元,反之亦然。可能有未命名的 在结构对象中填充,但不在其开头。

答案 1 :(得分:1)

你有一些问题,但这对我有用:

#include <malloc.h>
#include <stdio.h>

struct with_int {
    int a;
    char b;
};

int main(void)
{
    struct with_int *i = (struct with_int *)malloc(sizeof(struct with_int));
    i->a = 5;
    *(int *)i = 8;
    printf("%d\n", i->a);
}

输出是: 8

答案 2 :(得分:0)

就像其他答案指出的那样,我认为您的意思是:

// Interpret (struct with_int *) as (int *), then
// dereference it to assign the value 8.
*((int *) i) = 8;

而不是:

((int *) &i)->a = 8;

但是,没有一个答案能具体说明为什么该错误有意义。

让我解释一下((int *) &i)->a的含义:

i是一个变量,它保存一个(struct with_int)的地址。 &i是main()函数的堆栈空间上的地址。这意味着&i是一个地址,其中包含(struct with_int)的地址。换句话说,&i是指向(struct with_int)的指针。然后,强制转换(int *)会告诉编译器将此堆栈地址解释为int指针,即int的地址。最后,使用该->a,您要求编译器从此a指针中获取结构成员int,然后为其分配值8。从int指针中获取结构成员是没有意义的。因此,您得到error: request for member 'a' in something not a struct or union

希望这会有所帮助。