【问题标题】:How to increment a pointer address and pointer's value?如何增加指针地址和指针的值?
【发布时间】:2012-01-02 17:28:35
【问题描述】:

让我们假设,

int *p;
int a = 100;
p = &a;

以下代码实际上会做什么以及如何做?

p++;
++p;
++*p;
++(*p);
++*(p);
*p++;
(*p)++;
*(p)++;
*++p;
*(++p);

我知道,这在编码方面有点乱,但我想知道当我们这样编码时会发生什么。

注意:假设a=5120300的地址,它存储在地址为3560200的指针p中。现在,每条语句执行后p & a 的值是多少?

【问题讨论】:

  • 为什么不直接在调试器中运行呢?
  • 好吧.. 为什么不干脆试试看看? printf 将打印一个带有 %p 的指针
  • 如果你对行为感到好奇,就去玩弄它。只需编写一个简单的 c 程序来处理所有这些用例,看看它是否对您有意义。
  • @AndersK。也许OP期望未定义的行为? ...也许不是。

标签: c pointers


【解决方案1】:

首先,++ 运算符优先于 * 运算符,而 () 运算符优先于其他所有运算符。

其次,如果您没有将 ++number 运算符分配给任何内容,则 ++number 运算符与 number++ 运算符相同。区别是number++先返回number再递增number,而++number先递增再返回。

第三,通过增加一个指针的值,你将它增加它的内容的大小,也就是说你增加它就像你在一个数组中迭代一样。

所以,总结一下:

ptr++;    // Pointer moves to the next int position (as if it was an array)
++ptr;    // Pointer moves to the next int position (as if it was an array)
++*ptr;   // The value pointed at by ptr is incremented
++(*ptr); // The value pointed at by ptr is incremented
++*(ptr); // The value pointed at by ptr is incremented
*ptr++;   // Pointer moves to the next int position (as if it was an array). But returns the old content
(*ptr)++; // The value pointed at by ptr is incremented
*(ptr)++; // Pointer moves to the next int position (as if it was an array). But returns the old content
*++ptr;   // Pointer moves to the next int position, and then get's accessed, with your code, segfault
*(++ptr); // Pointer moves to the next int position, and then get's accessed, with your code, segfault

由于这里的案例很多,我可能会犯一些错误,如果我错了,请纠正我。

编辑:

所以我错了,优先级比我写的要复杂一点,在这里查看: http://en.cppreference.com/w/cpp/language/operator_precedence

【讨论】:

  • *ptr++,值不递增,指针递增。这些一元运算符具有相同的优先级,但它们的求值是从右到左的。该代码的意思是“从ptr指向的地方获取内容,然后增加ptr”。这是非常常见的 C 代码(是的,相当混乱)。请更正这一点,我将删除反对票。 *(ptr)++ 也一样,括号什么也不做。
  • 非常感谢 Lundin,我还有什么遗漏吗?
  • @Lundin 嗨,上面的答案现在更正了吗?谢谢。
  • @Unheilig 第一句仍然完全错误,后缀 ++ 优先于一元 * ,后者与前缀 ++ 具有相同的优先级。除此之外,它似乎还可以。
  • @felipemaia 你确定它会出现段错误吗?也许它只是未定义的行为?
【解决方案2】:

检查程序,结果如下,

p++;    // use it then move to next int position
++p;    // move to next int and then use it
++*p;   // increments the value by 1 then use it 
++(*p); // increments the value by 1 then use it
++*(p); // increments the value by 1 then use it
*p++;   // use the value of p then moves to next position
(*p)++; // use the value of p then increment the value
*(p)++; // use the value of p then moves to next position
*++p;   // moves to the next int location then use that value
*(++p); // moves to next location then use that value

【讨论】:

  • @alex 使用它意味着例如,考虑语句,'int *a = p++;'这里将使用指针“p”的第一个值,之后 p 将移动到下一个位置。因此,在执行上述语句后,'a' 将具有由'p' 指向的先前位置的地址,而'p' 将指向下一个位置。即首先使用 'p' 的值作为上面的赋值表达式,然后增加 'p' 的值以指向下一个位置
  • 简而言之,我认为他使用短语“使用它”来表示更正式的术语“分配”。就是这样。
【解决方案3】:

以下是各种“仅打印”建议的实例化。我觉得它很有启发性。

#include "stdio.h"

int main() {
    static int x = 5;
    static int *p = &x;
    printf("(int) p   => %d\n",(int) p);
    printf("(int) p++ => %d\n",(int) p++);
    x = 5; p = &x;
    printf("(int) ++p => %d\n",(int) ++p);
    x = 5; p = &x;
    printf("++*p      => %d\n",++*p);
    x = 5; p = &x;
    printf("++(*p)    => %d\n",++(*p));
    x = 5; p = &x;
    printf("++*(p)    => %d\n",++*(p));
    x = 5; p = &x;
    printf("*p++      => %d\n",*p++);
    x = 5; p = &x;
    printf("(*p)++    => %d\n",(*p)++);
    x = 5; p = &x;
    printf("*(p)++    => %d\n",*(p)++);
    x = 5; p = &x;
    printf("*++p      => %d\n",*++p);
    x = 5; p = &x;
    printf("*(++p)    => %d\n",*(++p));
    return 0;
}

返回

(int) p   => 256688152
(int) p++ => 256688152
(int) ++p => 256688156
++*p      => 6
++(*p)    => 6
++*(p)    => 6
*p++      => 5
(*p)++    => 5
*(p)++    => 5
*++p      => 0
*(++p)    => 0

我将指针地址转换为ints,以便可以轻松比较它们。

我用 GCC 编译它。

【讨论】:

  • 我会在操作后将其更改为包含 x 和 p 的值。
【解决方案4】:

关于“如何增加指针地址和指针的值?” 我认为++(*p++); 实际上定义良好并且可以满足您的要求,例如:

#include <stdio.h>

int main() {
  int a = 100;
  int *p = &a;
  printf("%p\n",(void*)p);
  ++(*p++);
  printf("%p\n",(void*)p);
  printf("%d\n",a);
  return 0;
}

它不是在序列点之前两次修改相同的东西。虽然对于大多数用途来说,我不认为这是一种好的风格 - 它对我来说有点太神秘了。

【讨论】:

  • 实际上,括号是不必要的:++*p++ 将成功地增加值和指针(后缀++ 绑定比取消引用* 更强,并且由于顺序而发生在前缀++ 之前)。仅当您需要在增加它@9​​87654327@ 之前的值时,才需要括号。如果您使用全前缀,++*++p 也可以在没有括号的情况下正常工作(但在指针增量之后增加指向的值)。
【解决方案5】:
        Note:
        1) Both ++ and * have same precedence(priority), so the associativity comes into picture.
        2) in this case Associativity is from **Right-Left**

        important table to remember in case of pointers and arrays: 

        operators           precedence        associativity

    1)  () , []                1               left-right
    2)  *  , identifier        2               right-left
    3)  <data type>            3               ----------

        let me give an example, this might help;

        char **str;
        str = (char **)malloc(sizeof(char*)*2); // allocate mem for 2 char*
        str[0]=(char *)malloc(sizeof(char)*10); // allocate mem for 10 char
        str[1]=(char *)malloc(sizeof(char)*10); // allocate mem for 10 char

        strcpy(str[0],"abcd");  // assigning value
        strcpy(str[1],"efgh");  // assigning value

        while(*str)
        {
            cout<<*str<<endl;   // printing the string
            *str++;             // incrementing the address(pointer)
                                // check above about the prcedence and associativity
        }
        free(str[0]);
        free(str[1]);
        free(str);

【讨论】:

  • 什么是关联性?
  • 在代码中你可以看到 *str++,现在 * 和 ++ 具有相同的优先级(外行术语相同的优先级),并且 *str++ 也没有使用括号分隔,如 *(str++) 或(*str)++,因此有必要如何评估它。所以从右到左意味着 (x = str++) 然后是 (y = *x)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多