【问题标题】:What does *--a = *--b mean in C*--a = *--b 在 C 中是什么意思
【发布时间】:2021-01-23 12:05:55
【问题描述】:

假设ab 是指针,

我的理解是*--a = *--b 是指使用指针算法从ab 中减去1,然后取消引用ab 并将它们设置为相等。

这是否等同于

--a;
--b;
*a=*b

同样,什么是

*a++ = *b++;

相当于?

【问题讨论】:

  • 你对*--a = *--b的理解是正确的。而*a++ = *b++ 应该不难弄清楚。
  • 第一个等同于您的建议(*--a = *--b; 等同于--a; --b; *a = *b;——这个问题被编辑了很多,因此我重复我正在评论的内容)。第二个(*a++ = *b++;)等价于*a = *b; a++; b++
  • 但是如果a == b呢?
  • 发布增量。原理与您的第一个示例相同,只是它发生在计算表达式之后。
  • @G.Sliepen — 怎么样?只要指针在取消引用时指向有效的某个位置,该代码就具有良好的格式和确定性。这意味着预递减的指针不应该指向数组的开头,因此在计算表达式之前,两个指针都不应该指向数组的开头。 (如果你的意思是*--a = *--a;,那么你就陷入了未定义的行为——没有人会知道会发生什么。)

标签: c operator-precedence pointer-arithmetic


【解决方案1】:
*––a = *––b 

逻辑上等价于

tmpa = a - 1
tmpb = b - 1
*tmpa = *tmpb
a = a - 1
b = b - 1

需要注意的是,ab*tmpa 的更新可以以任何顺序进行,这些更新甚至可以交错进行。实现也可以跳过临时变量并立即更新指针值:

a = a - 1
b = b - 1
*a = *b

但这不是必需的或保证的。同样,

*a++ = *b++

逻辑上等价于

tmpa = a
tmpb = b
*tmpa = *tmpb
a = a + 1
b = b + 1

对于ab*tmpa 的更新顺序有相同的注意事项。同样,实现可能会跳过使用临时对象并将其评估为

*a = *b
a = a + 1
b = b + 1

但这既不是必需的,也不是保证的。

【讨论】:

    【解决方案2】:

    *a++ = *b++;

    取消引用b 并将其分配给a 指向的位置。 ++ 是后缀运算符,因此*b 的当前值将分配给*a,然后两者都会递增。

    如果将其保留在 while 循环中,则 b 中的所有字符都将复制到 a,包括 \0。只要*a++ = *b++ 不是\0,这种情况就会继续,此时循环终止。

    while(*a++ = *b++);

    例子:

    #include <stdio.h>
    
    int main()
    {
        char a_arr[30]  = {0};
        char b_arr[] = "Hello,World";
        
        char *a = a_arr;
        char *b = b_arr;
        
        while(*a++ = *b++);
        
        puts(a_arr);
        puts(b_arr);
        
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      例子

      uint8_t *a = 1030; // POINTS TO ADDRESS 1030
      uint8_t *b = 1020; // POINTS TO ADDRESS 1020
      
      printf("%d", *(--a)); // PRINTS VALUE ON ADDRESS 1029
      printf("%d", *(b++)); // PRINTS VALUE ON ADDRESS 1021
      

      *(--a) 减去一个字节(一个地址),因为指针 a 指向一个字节(它是 uint8_t)。减法后,它会从地址中读取值。

      *(--something)你可以写成

      uint32_t *c = 1050;
      c -= 1; // SUBCTRACTS 4 BYTE ADDRESS FROM POINTER c
      print("%d", *c);
      

      你可能会问为什么是 4 个字节?因为指针c 指向四字节(uint32_tint32_t)数据。您可以使用sizeof(variable) 获取以字节为单位的数据大小。

      在您的情况下,假设指针 a 指向地址 40。指针b 指向地址50。

      • 地址39持有值1

      • 地址40持有值2

      • 地址50持有值10

      • 地址51持有值11

         uint8_t *a = 40;
         uint8_t *b = 50;
        
         printf("%d", *(--a));
         printf("%d", *(b++));
        

      首先printf 将打印值1。第二个printf 将打印值50。 在printf之后,指针a指向地址39,指针b指向地址51

      原因?在第一个printf 中,它将首先减去一个地址(同样,一个因为它指向一个字节值),然后它会取消引用值(这就是我们使用* 从指针地址读取值的原因)。

      在第二个printf 中,它将首先取消引用值,然后将指针向上移动一个地址。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-14
        • 2020-02-09
        • 2014-01-16
        • 1970-01-01
        • 1970-01-01
        • 2017-02-02
        • 2013-12-16
        • 2014-12-21
        相关资源
        最近更新 更多