【问题标题】:Not Understanding Pointer Arithmetic with ++ and --不了解使用 ++ 和 -- 的指针算术
【发布时间】:2011-11-21 16:53:00
【问题描述】:

所以,我正在通过http://cplusplus.com/doc/tutorial/pointers/ 学习指针,但我对指针算术部分一无所知。有人可以澄清一下,或者给我一个关于这个的教程,我可能会更好地理解。

我对所有括号里的东西特别困惑,比如*p++(*p)++*(p++) 等之间的区别。

【问题讨论】:

  • 您应该在 C++ 中查看 order of operations 和/或 operator precedence
  • 只是为了让我们可以定制我们的答案——您是否也对整数后缀运算符感到困惑?也就是int i=0; i++; (i)++;看懂了吗?而且,您了解指针运算的其他方面吗?你了解p+1*(p+1) = 3吗?
  • a) 你到底对什么感到困惑?你明白括号里的表达式吗? b) 不要使用指针。在 C++ 中几乎从来没有明确需要它们,如果你刚刚开始,也永远不需要。
  • @KerrekSB:迭代器使用相同的语法。用于迭代的原始指针并没有错,您只是想避免它们的生命周期管理。
  • @KerrekSB:没有 void 指针算术之类的东西,你不能对任何指向不完整类型的指针使用算术运算,void 只是其中一个例子。 std:vector<T>::iterator 可能是一个原始指针。理解指针算法是以元素而不是字节来衡量的,这是 C++ 的基础。

标签: c++ memory pointers


【解决方案1】:

*p++

对于这个,++* 具有更高的优先级,因此它将指针递增 1,但在原始位置检索值,因为后递增返回指针,然后递增其值。

(*p)++

这会强制另一个方向的优先级,因此首先取消引用指针,然后该位置的值加一(但返回原始指针位置的值)。

*(p++)

这个首先增加指针,所以它的行为与第一个相同。

需要注意的重要一点是,指针的递增量受指针类型的影响。从您提供的链接:

char *mychar;
short *myshort;
long *mylong;

char 的长度为一个字节,因此++ 将指针加 1(因为指针指向每个字节的开头)。

short 的长度为两个字节,因此++ 将指针增加 2 以指向下一个短字节的开头,而不是下一个字节的开头。

long 的长度为四个字节,因此++ 将指针增加 4。

【讨论】:

  • 好的,所以 (*p)++ 影响 p 指向的内容,*p++ 影响实际指针的内存位置。
  • 这个答案混淆了前置增量和后置增量。
  • @VinylScratch:没错,但是*p++(相当于*(p++))获取的是p所引用的值,然后再调整指针。
  • 这个答案提出的第一点大错特错。虽然 ++ 确实比 * 具有更高的优先级,但后缀 ++ 故意在递增之前返回该点的值,以便 *p++ 检索未递增位置的值。请解决这个问题。
  • short 不一定是两个字节的长度。它是短字节的大小。同样,long 是 sizeof long 字节。
【解决方案2】:

几年前我发现一个有用的 strcpy 解释,来自 Kernighan/Ritchie(我现在没有可用的文本,希望代码准确):cpy_0、cpy_1、cpy_2 都等同于 strcpy:

char *cpy_0(char *t, const char *s)
{
    int i = 0;
    for ( ; t[i]; i++)
        t[i] = s[i];
    t[i] = s[i];
    i++;
    return t + i;
}
char *cpy_1(char *t, const char *s)
{
    for ( ; *s; ++s, ++t)
        *t = *s;
    *t = *s;
    ++t;
    return t;
}
char *cpy_2(char *t, const char *s)
{
    while (*t++ = *s++)
        ;
    return t;
}

【讨论】:

    【解决方案3】:

    首先您必须了解后增量的作用;
    后递增,将变量增加一表达式 (p++) 返回要在表达式的其余部分中使用的变量的原始值。

    char   data[] = "AX12";
    char* p;
    
    p = data;
    char* a = p++;
    
    // a -> 'A'  (the original value of p was returned from p++ and assigned to a)
    // p -> 'X'
    
    p = data;   // reset;
    char  l =  *(p++);
    
    // l =  'A'. The (p++) increments the value of p. But returns the original
                 value to be used in the remaining expression. Thus it is the
                 original value that gets de-referenced by * so makeing l 'A'
    // p -> 'X'
    

    现在因为运算符优先级:

    *p++ is equivalent to *(p++)
    

    终于有了复杂的:

    p = data;
    char m = (*p)++;
    
    // m is 'A'. First we deference 'p' which gives us a reference to 'A'
    //           Then we apply the post increment which applies to the value 'A' and makes it a 'B'
    //           But we return the original value ('A') to be used in assignment to 'm'
    
    // Note 1:   The increment was done on the original array
    //           data[]  is now "BXYZ";
    // Note 2:   Because it was the value that was post incremented p is unchaged.
    // p -> 'B' (Not 'X')
    

    【讨论】:

      【解决方案4】:
      *p++
      

      返回内容,*p,然后增加指针的值(后增量)。例如:

      int numbers[2];
      int *p;
      p = &numbers[0];
      *p = 4;        //numbers[0] = 4;
      *(p + 1) = 8;  //numbers[1] = 8;
      int a = *p++;  //a = 4 (the increment takes place after the evaluation)
                     //*++p would have returned 8 (a = 8)
      int b = *p;    //b = 8 (p is now pointing to the next integer, not the initial one)
      

      关于:

      (*p)++
      

      增加内容的价值,*p = *p + 1;.

      (p++); //same as p++
      

      增加指针,使其指向声明指针时定义的大小的下一个元素(可能不存在)。

      【讨论】:

      • “增加它的价值”在这里是模棱两可的。它增加指针,而不是指针。
      • 我允许自己重述一下那部分,以确保它不会令人困惑。
      • 这是未定义的行为:*p = 4;
      • @lok​​i: 该表达式不是未定义的行为,它在未初始化的指针上完成的事实是 UB
      • @Necrolis:以后我会更加迂腐地解释我的解释,让它们非常明显。不仅仅是显而易见的。
      猜你喜欢
      • 2015-07-04
      • 1970-01-01
      • 1970-01-01
      • 2021-08-26
      • 2021-05-12
      • 2016-04-25
      • 2018-03-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多