Son*_*Ex2 5 c portability pointers language-lawyer
我编写了这个C代码,我假设它提供了可移植的标记指针:
typedef struct {
char tag[2];
int data;
} tagged_int;
#define TAG(x,y) (&(x)->tag[(y)])
#define UNTAG(x) (&(x)[-*(x)])
int main(void) {
tagged_int myint = {{0,1}, 33};
tagged_int *myptr = &myint;
char *myint_tag_1 = TAG(myptr,1);
char *myint_tag_0 = TAG(myptr,0);
char tag_1 = *myint_tag_1;
char tag_0 = *myint_tag_0;
tagged_int *myint_1 = UNTAG(myint_tag_1);
tagged_int *myint_0 = UNTAG(myint_tag_0);
}
Run Code Online (Sandbox Code Playgroud)
但是,我很好奇它是否真的可携带.
虽然数组操作部分是可移植的,但是转换是char *可struct *移植的,假设char *指的是第一个字段/元素struct *?(这很遗憾地输出编译器警告,但我猜你会得到带有"正常"标记指针的那些......)
#define UNTAG(x) (&(x)[-*(x)])不用作指向tagged_int;的指针 它是一个char *并且不会自动转换。
如果插入强制转换,#define UNTAG(x) ((tagged int *)(&(x)[-*(x)]))那么这几乎是合法的,根据 C 2011 (draft N1570) 6.7.2.1 15, \xe2\x80\x9cA 指向结构对象的指针,经过适当转换,指向其初始成员(或者如果该成员是一个位域,然后指向它所在的单元),反之亦然。\xe2\x80\x9d 这里的一个障碍是你有一个指向第一个成员的第一个成员的指针(即指向char一个数组的第 0 个元素,即第一个成员)。根据您对 C 标准中某些内容的解释严格程度,这可能会也可能不会被视为受支持(并且可以通过使用两次强制转换来缓解,如#define UNTAG(x) ((tagged int *)(char (*)[2])(&(x)[-*(x)])))。无论如何,我希望它是可移植的,因为 C 实现必须不遗余力地打破这一点,同时支持其他可接受的 C 语义。