user-0 提问: C语言中关于指针和++的问题。。

回复:
user: user-1
content: 引用 4 楼 u013106556 的回复:[quote=引用 3 楼 happyperson 的回复:] p是int型的指针，p++是按照sizeof(int)加的，最后*p是取的随机值 *p的值为随机值，意思是每次运行都不相同？但是每次运行后其值是相同的，都是1638212。。不知道你这个随机是如何理解的。。。[/quote] 这个跟编译器有关系。vs2012以上，就是会变的值。vs2010是固定的值。

user: user-2
content: 引用 19 楼 changyuanchn 的回复: 请注意他们的associativity。[/quote]  associativity 本身没有先后顺序 ++ 可以左结合，这时它是p++，即后缀++ 也可以右结合，这时它是++p,即前缀++  编译器，先判断出是前缀++，还是后缀++，然后区分++这个运算符的优先级 因为实质上++是两个不同的运算符，但是识别的时候，只能先识别 ++ ，再去判断 ++是前缀++，还是后缀++  *p++ 根据结合性，不能判定先执行哪一个。因为后缀++，--的特殊性，先计算 表达式 p++ 的值，在使用 p 的值（p++ ==p） 然后通过p 的值，得到*p 的值 结合性从来不是，判断先计算和后计算的依据，优先级才是 结核性判断的是这个符号，该和左边的表达式结合，还是右边的表达式  一旦判断出来结合性以后，就会用通过优先级，和操作数的个数，判断如何解读表达式。 associativity 结合性，是 判断符号（运算符）该和谁----左边的表达式，还是右边的表达式----结合，而不是判断一个变量或者表达式，该优先和那个符号（运算符）结合。  变量不过是表达式的一种终结符---原子表达式？不可分割的表达式的一种---在表达式的计算中，并无其他特殊含义。  associativity， priority 结合性和优先级，是两种不同的概念associativity 表明运算符该和哪一边结合 分为左结合，右结合，两边结合 ；++，-- 是一个形式，两种运算符，所以 是左，右二选一结合的，不是纯粹左结合的，也不是纯粹右结合的，也不是 两边结合的。  一般来说，双目运算符是两面结合的，单目运算符是单边结合的，一般是右结合的  单目运算符中，算术运算符，只有 ++，-- 可以左结合   因为++，--是单目运算符，，只能是单边结合的，但是这++，-- 运算符， 都有前缀形式，和后缀形式，所以必须先判断结合性，再在解读优先级，  其他运算符，优先级，结合性是直接给出的，不用判断。  哦，双目运算符[]，等也是比较特殊的， 左边是左操作数， []内部，是右操作数 因为右操作数，在运算符内部，所以这个运算符，是左结合的。  运算符的结合性，不能判断计算的顺序，比如 a+b/c

user: user-2
content: 引用 17 楼 changyuanchn 的回复:/quote] 在*iter++根本是不存在你说的“++优先级比*高”，对于这个问题的，你所谓的“++优先级比*高”是没有任何意义的，不去做无谓的戏份也是能够得到正确答案的。  *和++ 是相邻的两个运算符 如果 *的优先级高 ，那么 先  *p 结合，再对 (*p) 做++  ，就是 (*p)++了 如果 ++ 优先级高 ，那么 先 p++结合， 再对 (p++) 这个表达式 做 *  操作, 就是*(p++)了  *p++,*++p 这里的优先级是起作用的 ++的优先级，比一元 *的优先级高 所以 先 执行++ 在对表达式 p++执行 *操作   结果分别是是  1)*p++; *p++  的结果是 *p;副作用是 p++;  先后顺序是 *p; p++; 2)*++p *++p  的结果是 *(p+1);副作用是 ++p;  先后顺序是  ++p;*p 此时的 *p, 等于 ++前的*(p+1)   运算符的优先级，是指表达式计算过程中，相邻的两个运算符的优先级。 ++ 这种运算符和优先级的关系，是表达式计算的优先级，而不是 p ++这个表达式中， p自增的优先级。 ++ 在前， 自增先算； ++在后，自增后算；  自增的计算先后，只和 ++ 在前，在后有关；和优先级并无关系，有关系的是表达式的值。  ++在前， 使用的是自增后的结果。 ++在后，使用的是自增前的结果。  *p是从地址中取出其中储存的数据，这也是要计算的。 表达式计算的是表达式的结果，而不是 其中变量的值，  变量在计算表达式中，发生变化，是表达式计算的副作用，不是计算的主要任务 虽然，我们实际上需要的可能是变量的值，但是那不是表达式计算过程必须的。 只有在代码优化的时候，才有可能用取消表达式求值过程中，不需要的那部分。  比如  p++； 自增是我们需要的，但是 求 p++ 这个表达式的值， 才是表达式求值的任务，自增只是副作用而已。  使用C，C++始终要记住，变量，函数调用，等等都能够成为表达式，函数的实参实际上也是表达式。 C,C++语言一直都在计算表达式。 *iter++,*++iter 和指针 *p++,*++p;是一样的  因为  1）iterator 本来就可以实现为指针，也可以实现为类，结构这只和实现有关系 2）iterator 如果是个对象类型的化，那他 就必然实现 operator++(),operator--(), operator*()       那么，它的++，--，*的优先级和指针的一致。 3）STL 中的容器相关的算法，可以对指针使用，也可以对iterator 使用，因为这是 STL的设计目标。     就是说，数组也是为视为容器，虽然取数组大小比较麻烦。   PS： 如果，只从变量，来理解 *p++,*++p;这种表达式，显然是不够的。 这里是要考虑优先级的； 变量，只是构成表达式的一种元素，不是全部元素。

user: user-3
content: 我来指出一个问题和回答一个问题吧。 指出的问题是（！！接着，将p所存的内容加1）你把m=*p++后面过程理解错了。正解是这样的，实现m=*p，之后p指针自加一，因为你定义p是int型指针，那么p++就相当于（地址p）=（地址p）+（4bit），结果就是p还是一个地址，并且指向了下一个int型数据，而不是将p中的内容加1。 回答（*p的值又是如何确定的）：这么跟你解释吧，当计算机运行程序时，代码汇编成机器语言放在代码段（内存）中，而程序中的数据放在数据段（内存）中，当你定义int a=1是系统就在数据段中按照一定的算法找到不用的4bit地址，擦除它原来的数据重新赋值为2（注意是先擦除后赋值）。所以当p++之后p就指向了接下来的4bit地址，注意这个地址中的数据是没有擦除的（我们不知道有或者没有），总之它是一个随机数，因此*p的值是个随机数。 希望能帮到你，不用谢。

user: user-4
content: 引用查了一些资料，*p++本质是*(p++),即先考虑p++！而p++计算时，先使用p的值 对这些资料，只想说呵呵

user: user-5
content: 引用 18 楼 lm_whales 的回复:[quote=引用 17 楼 changyuanchn 的回复:] /quote] 在*iter++根本是不存在你说的“++优先级比*高”，对于这个问题的，你所谓的“++优先级比*高”是没有任何意义的，不去做无谓的戏份也是能够得到正确答案的。  *和++ 是相邻的两个运算符 如果 *的优先级高 ，那么 先  *p 结合，再对 (*p) 做++  ，就是 (*p)++了 如果 ++ 优先级高 ，那么 先 p++结合， 再对 (p++) 这个表达式 做 *  操作, 就是*(p++)了  *p++,*++p 这里的优先级是起作用的 ++的优先级，比一元 *的优先级高 所以 先 执行++ 在对表达式 p++执行 *操作   结果分别是是  1)*p++; *p++  的结果是 *p;副作用是 p++;  先后顺序是 *p; p++; 2)*++p *++p  的结果是 *(p+1);副作用是 ++p;  先后顺序是  ++p;*p 此时的 *p, 等于 ++前的*(p+1)   运算符的优先级，是指表达式计算过程中，相邻的两个运算符的优先级。 ++ 这种运算符和优先级的关系，是表达式计算的优先级，而不是 p ++这个表达式中， p自增的优先级。 ++ 在前， 自增先算； ++在后，自增后算；  自增的计算先后，只和 ++ 在前，在后有关；和优先级并无关系，有关系的是表达式的值。  ++在前， 使用的是自增后的结果。 ++在后，使用的是自增前的结果。  *p是从地址中取出其中储存的数据，这也是要计算的。 表达式计算的是表达式的结果，而不是 其中变量的值，  变量在计算表达式中，发生变化，是表达式计算的副作用，不是计算的主要任务 虽然，我们实际上需要的可能是变量的值，但是那不是表达式计算过程必须的。 只有在代码优化的时候，才有可能用取消表达式求值过程中，不需要的那部分。  比如  p++； 自增是我们需要的，但是 求 p++ 这个表达式的值， 才是表达式求值的任务，自增只是副作用而已。  使用C，C++始终要记住，变量，函数调用，等等都能够成为表达式，函数的实参实际上也是表达式。 C,C++语言一直都在计算表达式。 *iter++,*++iter 和指针 *p++,*++p;是一样的  因为  1）iterator 本来就可以实现为指针，也可以实现为类，结构这只和实现有关系 2）iterator 如果是个对象类型的化，那他 就必然实现 operator++(),operator--(), operator*()       那么，它的++，--，*的优先级和指针的一致。 3）STL 中的容器相关的算法，可以对指针使用，也可以对iterator 使用，因为这是 STL的设计目标。     就是说，数组也是为视为容器，虽然取数组大小比较麻烦。   PS： 如果，只从变量，来理解 *p++,*++p;这种表达式，显然是不够的。 这里是要考虑优先级的； 变量，只是构成表达式的一种元素，不是全部元素。  [/quote] 请注意他们的associativity。

user: user-5
content: 引用 15 楼 oYinGui1 的回复:[quote=引用 14 楼 changyuanchn 的回复:] [quote=引用 13 楼 oYinGui1 的回复:] [quote=引用 10 楼 changyuanchn 的回复:] 错了楼主，*p++的意思是先取p所指向的值，然后在将p++。因为*，++的优先级是一样的，结合度是从右向左，但是p++是先取p的值，然后在去++，而取出来的p，要先进性*p的运算。 ++优先级比*高，不论前缀还是后缀。。。。你说的优先级一样是从哪个表里看来的。。。[/quote] The C programming language. 二者的优先级是一致的，并没有去细分他们的高低，谭浩强的书中好像是有分吧，但是这没有什么意义。[/quote] 看对什么问题，CP5里是明确指出*iter++这种表达式的解释方法的，++优先级比*高。对于这种表达式确实要了解一下优先级。[/quote] 在*iter++根本是不存在你说的“++优先级比*高”，对于这个问题的，你所谓的“++优先级比*高”是没有任何意义的，不去做无谓的戏份也是能够得到正确答案的。

user: user-5
content: 引用 13 楼 oYinGui1 的回复:[quote=引用 10 楼 changyuanchn 的回复:] 错了楼主，*p++的意思是先取p所指向的值，然后在将p++。因为*，++的优先级是一样的，结合度是从右向左，但是p++是先取p的值，然后在去++，而取出来的p，要先进性*p的运算。 ++优先级比*高，不论前缀还是后缀。。。。你说的优先级一样是从哪个表里看来的。。。[/quote] The C programming language. 二者的优先级是一致的，并没有去细分他们的高低，谭浩强的书中好像是有分吧，但是这没有什么意义。

user: user-6
content: 如果搞不清楚操作符优先级的顺序，用下面的方法 1. () 你要明确地操作， 如 *(p++), (*p)++ 2. 分成多行书写：    a = *p++; -->      a = *p;     p++;

user: user-7
content: 引用 14 楼 changyuanchn 的回复:[quote=引用 13 楼 oYinGui1 的回复:] [quote=引用 10 楼 changyuanchn 的回复:] 错了楼主，*p++的意思是先取p所指向的值，然后在将p++。因为*，++的优先级是一样的，结合度是从右向左，但是p++是先取p的值，然后在去++，而取出来的p，要先进性*p的运算。 ++优先级比*高，不论前缀还是后缀。。。。你说的优先级一样是从哪个表里看来的。。。[/quote] The C programming language. 二者的优先级是一致的，并没有去细分他们的高低，谭浩强的书中好像是有分吧，但是这没有什么意义。[/quote] 看对什么问题，CP5里是明确指出*iter++这种表达式的解释方法的，++优先级比*高。对于这种表达式确实要了解一下优先级。

user: user-7
content: 引用 10 楼 changyuanchn 的回复:错了楼主，*p++的意思是先取p所指向的值，然后在将p++。因为*，++的优先级是一样的，结合度是从右向左，但是p++是先取p的值，然后在去++，而取出来的p，要先进性*p的运算。 ++优先级比*高，不论前缀还是后缀。。。。你说的优先级一样是从哪个表里看来的。。。

user: user-8
content: m = *p++; 这句，考的是运算符优先级的问题，如果是题目，那么你就按照教科书上的优先级来做，具体哪个运算符优先，我也拿不实在了。如果是编写实际的项目，那么你遇到这种有可能有歧义的情况，最好用括号表明优先级，因为有些编译器并不标准，这种情况可能不同的编译器有不同的结果。  ————————  P是指向a的指针，而a只是一个变量，进行p++运算之后，p就指到了a后面，但是a后面不一定是b，这也是依赖于编译器的，a、b、m的存放顺序病没有一个标准。

user: user-9
content: //C++ Operators //  Operators specify an evaluation to be performed on one of the following: //    One operand (unary operator) //    Two operands (binary operator) //    Three operands (ternary operator) //  The C++ language includes all C operators and adds several new operators. //  Table 1.1 lists the operators available in Microsoft C++. //  Operators follow a strict precedence which defines the evaluation order of //expressions containing these operators.  Operators associate with either the //expression on their left or the expression on their right;    this is called //“associativity.” Operators in the same group have equal precedence and are //evaluated left to right in an expression unless explicitly forced by a pair of //parentheses, ( ). //  Table 1.1 shows the precedence and associativity of C++ operators //  (from highest to lowest precedence). // //Table 1.1   C++ Operator Precedence and Associativity // The highest precedence level is at the top of the table. //+------------------+-----------------------------------------+---------------+ //| Operator         | Name or Meaning                         | Associativity | //+------------------+-----------------------------------------+---------------+ //| ::               | Scope resolution                        | None          | //| ::               | Global                                  | None          | //| [ ]              | Array subscript                         | Left to right | //| ( )              | Function call                           | Left to right | //| ( )              | Conversion                              | None          | //| .                | Member selection (object)               | Left to right | //| ->               | Member selection (pointer)              | Left to right | //| ++               | Postfix increment                       | None          | //| --               | Postfix decrement                       | None          | //| new              | Allocate object                         | None          | //| delete           | Deallocate object                       | None          | //| delete[ ]        | Deallocate object                       | None          | //| ++               | Prefix increment                        | None          | //| --               | Prefix decrement                        | None          | //| *                | Dereference                             | None          | //| &                | Address-of                              | None          | //| +                | Unary plus                              | None          | //| -                | Arithmetic negation (unary)             | None          | //| !                | Logical NOT                             | None          | //| ~                | Bitwise complement                      | None          | //| sizeof           | Size of object                          | None          | //| sizeof ( )       | Size of type                            | None          | //| typeid( )        | type name                               | None          | //| (type)           | Type cast (conversion)                  | Right to left | //| const_cast       | Type cast (conversion)                  | None          | //| dynamic_cast     | Type cast (conversion)                  | None          | //| reinterpret_cast | Type cast (conversion)                  | None          | //| static_cast      | Type cast (conversion)                  | None          | //| .*               | Apply pointer to class member (objects) | Left to right | //| ->*              | Dereference pointer to class member     | Left to right | //| *                | Multiplication                          | Left to right | //| /                | Division                                | Left to right | //| %                | Remainder (modulus)                     | Left to right | //| +                | Addition                                | Left to right | //| -                | Subtraction                             | Left to right | //| <<               | Left shift                              | Left to right | //| >>               | Right shift                             | Left to right | //| <                | Less than                               | Left to right | //| >                | Greater than                            | Left to right | //| <=               | Less than or equal to                   | Left to right | //| >=               | Greater than or equal to                | Left to right | //| ==               | Equality                                | Left to right | //| !=               | Inequality                              | Left to right | //| &                | Bitwise AND                             | Left to right | //| ^                | Bitwise exclusive OR                    | Left to right | //| |                | Bitwise OR                              | Left to right | //| &&               | Logical AND                             | Left to right | //| ||               | Logical OR                              | Left to right | //| e1?e2:e3         | Conditional                             | Right to left | //| =                | Assignment                              | Right to left | //| *=               | Multiplication assignment               | Right to left | //| /=               | Division assignment                     | Right to left | //| %=               | Modulus assignment                      | Right to left | //| +=               | Addition assignment                     | Right to left | //| -=               | Subtraction assignment                  | Right to left | //| <<=              | Left-shift assignment                   | Right to left | //| >>=              | Right-shift assignment                  | Right to left | //| &=               | Bitwise AND assignment                  | Right to left | //| |=               | Bitwise inclusive OR assignment         | Right to left | //| ^=               | Bitwise exclusive OR assignment         | Right to left | //| ,                | Comma                                   | Left to right | //+------------------+-----------------------------------------+---------------+

user: user-5
content: 错了楼主，*p++的意思是先取p所指向的值，然后在将p++。因为*，++的优先级是一样的，结合度是从右向左，但是p++是先取p的值，然后在去++，而取出来的p，要先进性*p的运算。

user: user-9
content: Addition (+) The addition operator (+) causes its two operands to be added. Both operands can be either integral or floating types, or one operand can be a pointer and the other an integer.    When an integer is added to a pointer, the integer value (i) is converted by multiplying it by the size of the value that the pointer addresses. After conversion, the integer value represents i memory positions, where each position has the length specified by the pointer type. When the converted integer value is added to the pointer value, the result is a new pointer value representing the address i positions from the original address. The new pointer value addresses a value of the same type as the original pointer value and therefore is the same as array indexing (see One-Dimensional Arrays and Multidimensional Arrays). If the sum pointer points outside the array, except at the first location beyond the high end, the result is undefined. For more information, see Pointer Arithmetic.   Subtraction (–) The subtraction operator (–) subtracts the second operand from the first. Both operands can be either integral or floating types, or one operand can be a pointer and the other an integer.    When two pointers are subtracted, the difference is converted to a signed integral value by dividing the difference by the size of a value of the type that the pointers address. The size of the integral value is defined by the type ptrdiff_t in the standard include file STDDEF.H. The result represents the number of memory positions of that type between the two addresses. The result is only guaranteed to be meaningful for two elements of the same array, as discussed in Pointer Arithmetic.   When an integer value is subtracted from a pointer value, the subtraction operator converts the integer value (i) by multiplying it by the size of the value that the pointer addresses. After conversion, the integer value represents i memory positions, where each position has the length specified by the pointer type. When the converted integer value is subtracted from the pointer value, the result is the memory address i positions before the original address. The new pointer points to a value of the type addressed by the original pointer value.  Pointer Arithmetic Additive operations involving a pointer and an integer give meaningful results only if the pointer operand addresses an array member and the integer value produces an offset within the bounds of the same array. When the integer value is converted to an address offset, the compiler assumes that only memory positions of the same size lie between the original address and the address plus the offset.  This assumption is valid for array members. By definition, an array is a series of values of the same type; its elements reside in contiguous memory locations. However, storage for any types except array elements is not guaranteed to be filled by the same type of identifiers. That is, blanks can appear between memory positions, even positions of the same type. Therefore, the results of adding to or subtracting from the addresses of any values but array elements are undefined.  Similarly, when two pointer values are subtracted, the conversion assumes that only values of the same type, with no blanks, lie between the addresses given by the operands.

user: user-10
content: 引用 7 楼 u013106556 的回复:[quote=引用 6 楼 czarten 的回复:] [quote=引用 5 楼 u013106556 的回复:] [quote=引用 2 楼 czarten 的回复:] 关于*p，首先我这边试了一下结果是6，其次输出指针不应该用%d 我这边运行最后*p的值不是6；其次，不用%d??  说下原因吧！！！[/quote]  确实应该是随机值，因为你的p前面一直指向a，而在最后一句p++使得p指向了a后面的一格内存，而这格内存上没有你的变量，因此结果不定  不用%d是说你前面的p和&a，应该用%p输出[/quote]谢谢 你怎么了熊吉！！  还是不清楚这个随机值是怎么随机的。。。[/quote]  此处的“随机”不是说你每次运行会得到一个不同的值，而是说结果无法预料，可能取决于编译器和运行环境等。 比如我这边，输出*p是6，这意味着我的编译器把b变量放在紧接着a的后面，所以原先指向a指针++之后刚好指向了b，但这并不是C语言规定的，换个编译器可能就不这么放了

user: user-0
content: 引用 6 楼 czarten 的回复:[quote=引用 5 楼 u013106556 的回复:] [quote=引用 2 楼 czarten 的回复:] 关于*p，首先我这边试了一下结果是6，其次输出指针不应该用%d 我这边运行最后*p的值不是6；其次，不用%d??  说下原因吧！！！[/quote]  确实应该是随机值，因为你的p前面一直指向a，而在最后一句p++使得p指向了a后面的一格内存，而这格内存上没有你的变量，因此结果不定  不用%d是说你前面的p和&a，应该用%p输出[/quote]谢谢 你怎么了熊吉！！  还是不清楚这个随机值是怎么随机的。。。

user: user-10
content: 引用 5 楼 u013106556 的回复:[quote=引用 2 楼 czarten 的回复:] 关于*p，首先我这边试了一下结果是6，其次输出指针不应该用%d 我这边运行最后*p的值不是6；其次，不用%d??  说下原因吧！！！[/quote]  确实应该是随机值，因为你的p前面一直指向a，而在最后一句p++使得p指向了a后面的一格内存，而这格内存上没有你的变量，因此结果不定  不用%d是说你前面的p和&a，应该用%p输出

user: user-0
content: 引用 2 楼 czarten 的回复:关于*p，首先我这边试了一下结果是6，其次输出指针不应该用%d 我这边运行最后*p的值不是6；其次，不用%d??  说下原因吧！！！

user: user-0
content: 引用 3 楼 happyperson 的回复:p是int型的指针，p++是按照sizeof(int)加的，最后*p是取的随机值 *p的值为随机值，意思是每次运行都不相同？但是每次运行后其值是相同的，都是1638212。。不知道你这个随机是如何理解的。。。