C: 运算符 -> 和 *

C: operator -> and *

在下面的例子中:

typedef struct {
    const char *description;
    float value;
} swag;

typedef struct {
    swag *swag;
    const char *sequence;
} combination;

typedef struct {
    combination numbers;
    const char *make;
} safe;

int main()
{
    swag gold = {"GOLD!", 1000000.0};
    combination numbers = {&gold, "6502"};
    safe s = {numbers, "RAMACON250"};

    //Correct handling
    printf("Result: %s \n", s.numbers.swag->description);

    //Faulty handling
    // printf("Result: %s \n", s.numbers.(*swag).description);

    return 0;
}

为了接收 "GOLD!"

以下行是正确的
printf("Result: %s \n", s.numbers.swag->description);

但为什么以下内容不正确,因为 (*x).yx->y

相同
printf("Result: %s \n", s.numbers.(*swag).description);

我在编译过程中收到以下错误:

C:\main.c|26|error: expected identifier before '(' token|)

只需使用

printf("Result: %s \n", ( *s.numbers.swag).description);

根据 C 语法,后缀表达式 . 定义如下

postfix-expression . identifier

所以你可以这样写

( identifier1 ).identifier2

但你可能不会写

identifier1.( identifier2 )

回到你的程序你甚至可以写

printf("Result: %s \n", ( *( ( ( s ).numbers ).swag ) ).description);

只需将 *swag 替换为 swag[0]。

printf("Result: %s \n", s.numbers.swag[0].description);

记住 *swag 和 swag[0] 是一回事。

why the following is not correct as the (*x).y is same as x->y

printf("Result: %s \n", s.numbers.(*swag).description);

关于 (*x).yx->y

相同的说法是正确的

但这不是您在代码中所做的:

s.numbers.(*swag).description

这样看:

when comparing s.numbers.swag->description to x->y

x is s.numbers.swag
y is description

so by simple substitution

x->y equivalent to (*x).y becomes (*s.numbers.swag).description

.->运算符优先级相同,结合性从左到右。这就是为什么

s.numbers.swag->description

工作正常。而且,凭直觉,您可以从左到右跟踪已解决的问题。 您访问 s 然后 numbers 然后 swag,您取消引用以访问 description.

你犯的错误是得出结论,因为a->b等价于(*a).b,表达式

s.numbers.(*swag).description

应该等同于上面那个。事实并非如此。

那是因为(一元)*运算符的优先级低于.->,而且它的结合性是从右到左的,加上括号不解决这个问题(您想访问 swag 指针而不是 swag 成员)。

有效的做法是:访问 s 然后 numbers 然后取消引用 swag(数字)并尝试访问 description。但是 numbers 只有一个指向 swag 而不是 swag 成员的指针。

另一个答案中已经提到了等价的表达式,为了完整起见,我在这里重复一下:

(*s.numbers.swag).description

访问 s 然后 numbers 然后 swag 然后访问描述。 请记住 . 的优先级高于 * 并且由于从左到右的关联性,括号在 . 之前解析以访问描述。

s.numbers.swag[0].description

访问 s 然后 numbers 然后 swag 并取消引用访问描述。 [] 运算符与 . 具有相同的优先级和结合性。所以你可以从左到右阅读这个表达式。