【发布时间】:2021-05-04 11:25:16
【问题描述】:
假设我有类似的东西:
在 list.h 中:
//...
#include <stdlib.h>
typedef struct node_s{
struct node_s *next;
struct node_s *prev;
char data[];
}node_t;
void* getDataFromNode(node_t *node){
return(node->data);
}
node_t* newNode(size_t size){
node_t *ret = malloc(sizeof(node_t));
return(ret);
}
//...
在 main.c 中:
#include "list.h"
#include <stddef.h>
typedef struct float_node_s{
struct foo_node_s *next;
struct foo_node_s *prev;
float someFloat;
}float_node_t;
int main(void){
float *f;
float_node_t *node;
//1)
node = (float_node_t*)newNode(sizeof(float_node_t));
if(node == NULL){
return(1);
}
//2)
f = (float*)getDataFromNode((node_t*)node);
return(0);
}
这是我在很多 C 列表/树/等中看到的。实现。
我可以这样做吗?
具体来说,我可以将node_t 指针转换为float_node_t 指针并将其分配给float_node_t 指针变量,如1)?如果我现在取消引用float_node_t 指针以访问存储在其中的浮点数怎么办?我猜2)已经被禁止了。返回的指针指向char 数组,它被强制转换为float 指针。
C 标准规定,指向不同结构的指针具有相同的表示和对齐要求,不会发生结构元素的重新排序,并且如果结构具有共同的初始序列,则这些结构的初始序列的布局将是相同的。
因此,转换指针和取消引用以访问 prev/next 字段似乎很好,但这不是已经违反了 C 的严格别名规则吗?
关于在“兼容”结构之间转换指针有很多类似的问题,但答案通常不同意甚至相互矛盾。有人说,通过任何一个指针访问公共初始序列的字段都可以,有人说你甚至不能取消引用强制转换的指针。
【问题讨论】:
-
从法律上讲,您需要使用联合。此外,
f = (float*)getDataFromNode((node_t*)node);假定生成的指针将正确对齐。
标签: c pointers struct language-lawyer