Это портативный способ сделать теговые указатели в C? - PullRequest
0 голосов
/ 01 июля 2018

Я написал этот код 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);
}

Однако мне любопытно, действительно ли он портативен.

Несмотря на то, что части манипулирования массивом переносимы, можно ли преобразовать char * в struct *, если допустить, что char * относится к первому полю / элементу в struct *? (Это печально выводит предупреждения компилятора, но я думаю, вы все равно получите те, у которых есть «нормальные» теговые указатели ...)

1 Ответ

0 голосов
/ 01 июля 2018

#define UNTAG(x) (&(x)[-*(x)]) не служит указателем на tagged_int; это char * и не будет автоматически конвертировано.

Если вы вставите приведение, #define UNTAG(x) ((tagged int *)(&(x)[-*(x)])), то это почти законно для C 2011 (черновик N1570) 6.7.2.1 15, «Указатель на объект структуры, соответствующим образом преобразованный, указывает на его начальный член (или, если это member является битовым полем, затем к единице, в которой он находится), и наоборот ». Препятствием здесь является то, что у вас есть указатель на первый член первого члена (то есть на char, то есть элемент 0 массива, который является первым членом). В зависимости от того, насколько строго вы интерпретируете определенные вещи в стандарте C, это может или не может считаться поддерживаемым (и может быть уменьшено с помощью двух приведений, как в #define UNTAG(x) ((tagged int *)(char (*)[2])(&(x)[-*(x)]))). В любом случае, я ожидал бы, что он будет переносимым, поскольку реализация C должна была бы изо всех сил сломать это, поддерживая другую принятую семантику C.

...