如何增加指针地址和指针的值?


96

让我们假设

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

以下代码将实际执行什么操作以及如何执行?

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

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

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


3
您为什么不只在调试器中运行它?
2011年

24
好吧..为什么不简单尝试一下看看呢?printf将使用%p打印一个指针
Brian Roach

如果您对行为感到好奇,请尝试一下。只需编写一个简单的遍历所有这些用例的c程序,然后查看它是否对您有意义。
赛勒斯(Cyrus)

@AndersK。也许OP期望未定义的行为?...或者可能不是。
Mateen Ulhaq

Answers:


174

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

其次,如果您没有将++ 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 of ptr is incremented
++(*ptr); // The value of ptr is incremented
++*(ptr); // The value of 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 of 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


6
* ptr ++,该值不增加,指针增加。这些一元运算符具有相同的优先级,但是从右到左进行评估。该代码的意思是“从ptr指向的位置获取内容,然后递增ptr”。这是非常常见的C代码(是的,非常令人困惑)。请更正此问题,我将删除该否决票。与*(ptr)++相同,括号不执行任何操作。
伦丁

非常感谢隆丁,我还想念其他吗?
felipemaia 2011年

@Lundin嗨,上面的答案现在纠正了吗?谢谢。
Unheilig 2014年

4
@Unheilig第一句话仍然是完全错误的,后缀++优先于一元*,后者的优先级与前缀++相同。除此之外,似乎还可以。
伦丁2014年

4
@felipemaia您确定它会出现段错误吗?也许只是不确定的行为?
jotik '16

13

检查了程序,结果是,

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

2
@alex使用它意味着例如考虑以下语句:'int * a = p ++;' 这里将使用指针“ p”的第一个值,之后,p将移至下一个位置。因此,实际上,执行上述语句后,“ a”将具有由“ p”指向的先前位置的地址,而“ p”将指向下一个位置。也就是说,首先使用上述赋值表达式的'p'值,然后将'p'的值递增以指向下一个位置
Sujith R Kumar

简而言之,我认为他在更正式的术语“分配”中使用短语“使用它”。就这些。
Apekshik Panigrahi

4

以下是各种“只打印它”建议的实例。我发现它很有启发性。

#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编译了它。


1
我将其更改为在操作后包括x和p的值。
NetJohn

3

关于“如何增加指针地址和指针的值?” 我认为这++(*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++将成功地增加value和指针(后缀++绑定比dereference绑定更强*,并且++由于顺序而发生在前缀之前)。仅当需要在增加值之前使用括号时,才需要使用括号(*p++)++。如果使用全前缀,++*++p也可以在没有括号的情况下正常工作(但在指针增加之后增加指向的值)。
cmaster-恢复莫妮卡

1
        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);

什么是关联性?
71GA

1
在代码中您可以看到* str ++,现在*和++都具有相同的优先级(在外行术语中具有相同的优先级),并且* str ++也不使用*(str ++)或(* str)++等括号分隔,因此有必要对其进行评估。所以从右到左表示(x = str ++),然后(y = * x)
Abhishek DK
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.