C指针说到底就是一种操作符,所以想要正确的理解C指针,那么最重要的就是莫过于理解操作符了
为了理解有些操作符存在的限制,你必须理解左值和右值(左值和右值)之间的区别。这两个术语是多年前由编译器设计者所创造并沿用至今。
左值就是那些能够出现在赋值符号左边的东西。右值就是那些可以出现在赋值符号右边的东西。这里有一例子:
a=b+25;
a是一个左值,因为它标识了一个可以存储结果的地点,b+25是一个右值,因为它指定了一个值。
那它们能够互换吗?
b+25=a;
原先作为左值的a此时也可以作为右值出现,因为每个位置都包含一个值。然而,b+25不能作为一个左值,因为它并没有标识一个特定的位置。因此上述语句非法。
注意当计算机计算b+25时,它的结果必然保存在机器的某个地方。但是,程序员并没有办法预测该结果会存储在什么地方,也无法保证下一次还会保存在那个地方。故其结果是:这个表达式不是一个左值。同样的道理:字面值常量字面值常量也都不是左值。
听上去似乎变量可以作为左值而表达式不能作为左值,但这个推断并不准确。下面请看一例子:
int a[10];
...
a[b+10]=0;
下标引用实际上是一个操作符,所以表达式的左边实际上是一个表达式,但它却是一个合法的左值,因为它标识一个特定的位置,我们可以使用它,再看一指针例子:
int a,*p;
...
pi=&a;
*p=20;
请看*p=20;
它的左边很明显是一个表达式,但它却是一个合法的左值,为什么呢?指针p的值是内存中某个特定位置的地址,*操作符使机器指向那个位置。
当它作为左值使用的时候,这个表达式指定需要修改的位置。当它作为右值使用时,它就提取当前存储在这个位置的值。
这下大家伙明白了吧,所谓的指针无非就是这么用的,这也很好的理解了为何指针可以去修改一些变量的值,说到底就是*
操作符是左值还是右值的原因,当它为左值的时候那就是指向要修改的位置,为右值则提取当前位置的值。
总结
左值和右值很好的解释了一些本质上的东西,特别是知晓了为何C语言语句的左边和右边会有如此大的区别,左值需要的是一个可以合理标识一个可以存储结果值的地点,前面提到变量其实在汇编语句中就是地址的代名词,而C语言编译之后就是汇编语句了,所以变量可以标识一个位置,放在左边可以当左值。
函数调用顺序
前面说到操作符,一般操作符都有所谓的优先级等等,故而就有什么运算的先后顺序,然而这里有个例外,函数的调用就是这个例外,举个例子
代码
#include<stdio.h>
int func()
{
int c;
c+=1;
return c;
}
int main()
{
int a;
a=func()+func()*func();
printf("the value=%d",a);
return 0;
}
这里我们可以看到程序执行起来似乎是有些问题的,这就是函数调用不按常理出牌的原因,因为所谓的C语言标准并没有对此做出过规定,上述代码结果为2,换做其他的可能是这样执行的:2+3*4,或者是3+2*4,或者是4+2*3也说不定的事情,所以函数调用的顺序颇为杂乱,因编译器而异,故而一般在做可移植性的代码时,此类语句还是不要出现的为好。