是否有理由使用像这样的&(* foo)的C语言指针?

时间:2017-09-11 19:01:36

标签: c pointers

当我需要更改指针的原始内存地址时,我会使用这样的代码编码。

示例:

static void get_line_func(struct data_s *data,
                                char **begin)
{
    data->slot_number = strsep(&(*(begin)), "/");
    data->protocol = *begin;
    strsep(&(*begin), ">");
    data->service_name = strsep(&(*begin), "\n");
}

我的意思是,不是&(*foo) == foo

1 个答案:

答案 0 :(得分:6)

没有理由直接这样做。但是,组合可能出现在机器生成的代码中(例如扩展预处理器宏)。

例如,假设我们有一个宏do_something_to(obj),它希望参数表达式obj指定一个对象。假设在其扩展中的某个位置,此宏使用&(obj)获取对象的地址。现在假设我们想将宏应用于我们只通过指针ptr保存的对象。要指定对象,我们必须使用表达式*ptr,以便我们将宏用作do_something_to(*ptr)。这当然意味着&(*ptr)现在出现在程序中。

多年来,表达式&*ptr的状态发生了变化。我似乎记得在ANSI C 89 / ISO C90方言中,如果ptr是无效指针,表达式会产生未定义的行为。

在ISO C11中,以下内容已拼写出来(我相信几乎相同的文本在C99中),要求&*不要取消引用指针:“如果操作数[地址 - 的一元&运算符]是一元*运算符的结果, 该运算符和&运算符都不会被评估,结果就像两者都一样 省略,除了对运算符的约束仍然适用且结果不是左值“。因此在现代C语言中,表达式&*ptr不会解除引用ptr,因此具有即使该值为null,也定义了行为。

这是什么意思? “约束仍然适用”基本上意味着它仍然需要键入检查。仅仅因为&*P没有取消引用P并不意味着P可以是doublestruct;它必须是指针。

“结果不是左值”部分可能有用。如果我们有一个值为P的指针,如果我们将它包装在表达式&*P中,我们将得到与非左值相同的指针值。还有其他方法可以获得P作为非左值的值,但&*P是一个“代码高尔夫”解决方案,只需要两个字符的问题,并具有保持正确的属性即使P从一种指针类型更改为另一种指针类型。