【问题标题】:operator precedence from page132 in K&RK&R 中第 132 页的运算符优先级
【发布时间】:2021-09-10 11:47:26
【问题描述】:

我在看K&R,卡在下面这句话里了。

*p -> str++ 在访问它指向的任何内容后都会递增 str(就像 *s++)

我同意它对*p -> str++ 的说法,但对于*s++,这对我来说没有任何意义。我想 *s++ 将在 s 递增之后访问它指向的任何内容,就像 (*s)++

【问题讨论】:

  • 解决所有这些头痛问题的方法是在同一个表达式中简单地not混合++ 运算符和其他运算符。它是无数错误的来源,几乎不存在真正需要混合它们的情况。在阅读 K&R 时,您会发现很多不好的做法,我建议您将这本书视为 1970 年代的古代遗物,而不是学习资料。

标签: c operator-precedence


【解决方案1】:

我认为*s++ 将在递增s 之后访问它指向的任何内容,就像(*s)++ 一样

这将使指针加一:

*s++;

这将使取消引用的指针(即它指向的指针)增加一:

(*s)++;

所以,这不是一回事。

例子:

#include <stdio.h>

int main() {
    char string[] = "Hello";
    
    char *s1 = string;

    printf("%c\n", *s1++);          // 'H'
    printf("%c\n", *s1);            // 'e'
    printf("%s\n", s1);             // "ello"

    char *s2 = string;

    printf("%c\n", (*s2)++);        // 'H'
    printf("%c\n", *s2);            // 'I'  ('H' + 1 = 'I')
    printf("%s\n", s2);             // "Iello"
}

【讨论】:

    【解决方案2】:

    -&gt; 和后缀++ 都比* 具有更高的precedence,具有从左到右的关联性。

    表达式*p-&gt;str++首先可以读作*(p-&gt;str)++,这在语义上与*s++相同,而*s++又可以读作*(s++)。所以是的,间接将发生在 增量 (expr++) 之后,但是

    后缀递增和递减运算符的结果是expr的值。

    因此,

    • p-&gt;str,或s,产生一个适合++(本例中的指针类型)的可修改左值。

    • ++(后缀)然后就地递增这个值,计算为表达式before递增的值。

    • * 对该指针值执行间接寻址。

    而(*s)++ 将在增加结果值之前执行间接。

    【讨论】:

    • 一元运算符本身不具有“关联性”——它们从内向外应用,最接近主表达式的运算符首先应用。他们真的没有其他方法可以申请。
    • 这在链接页面的注释部分关于运算符优先级进行了介绍,并详细说明了一元词缀和成员访问运算符。
    【解决方案3】:

    这里重要的是s++ 的返回值。您需要记住s++ 的返回值 是s。所以* 将取消引用地址s 有之前增量。

    所以代码*s++等价于

    T* temp = s; \___ These two lines is what s++ is doing
    s = s + 1;   /
    *temp;
    

    即*s++ 读取 s 指向的内容并将 s 加一。

    注意:要在阅读s 所指向的内容之前增加,您可以使用*++s。

    【讨论】:

      【解决方案4】:

      我认为 *s++ 会在 s 递增之后访问它所指向的任何内容,就像 (*s)++

      不。 *s++ 被解析为 *(s++) - 您正在取消引用 s++ 的 result。 s++ 的结果是s 的当前值;递增s 的副作用不会影响结果。从逻辑上讲,它的工作原理类似于

      tmp = s
      x = *tmp   // where "x =" represents any operation using the value of *tmp
      s = s + 1
      

      需要注意的是,最后两个操作可以以任何顺序发生,甚至可以同时发生(如果架构支持,则交错或并行)。

      (*s)++ 增加 *s 的 result - 这在逻辑上等同于写作

      tmp = *s
      x = tmp     // same as above
      *s = *s + 1
      

      与上述相同的警告。

      【讨论】:

        猜你喜欢
        • 2011-07-07
        • 2021-10-25
        • 2015-03-20
        • 2019-06-10
        • 2011-06-21
        • 2013-02-24
        • 2012-08-10
        相关资源
        最近更新 更多