Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1839284
  • 博文数量: 333
  • 博客积分: 10791
  • 博客等级: 上将
  • 技术积分: 4314
  • 用 户 组: 普通用户
  • 注册时间: 2007-08-08 07:39
文章分类

全部博文(333)

文章存档

2015年(1)

2011年(116)

2010年(187)

2009年(25)

2008年(3)

2007年(1)

分类: C/C++

2010-04-24 14:42:05

1、内存与地址
    对于C程序员来说:1)内存中的每个位置由一个独一无二的地址标识;2)内存中的每个位置都包含一个值。所以只要记住地址——硬件仍然可以通过地址访问内存位置。当然了,不能简单的通过检查一个值来判断它的类型,要看看是整型算数指令还是其他指令去判断

2、指针的初始化与NULL指针
    如果指针变量是静态的,它会被初始化为0;但如果变量是自动的,它根本不会被初始化。无论那种情况,声明一个指针都不会“创建”用于存储的内存空间。所以,在声明一个指针时最好将其初始化为NULL。
    那么什么是NULL指针呢?
    NULL指针是一个特殊的指针变量,表示不指向任何东西,NULL的值为“0”。
 
3、指针的使用
    指针变量可以作为左值,并不是因为它们是指针,而是因为它们是变量。
    指针的间接访问:*&a = 25;什么意思?它把值25赋给变量a。那么与表达式 a = 25有啥区别?功能上说,没区别。但是*&a = 25 的额外操作很多,可读性变差。 

4、指针的指针
    啊!有点恶心~~记住和二维数组的原来相似~~

5、指针表达式
    声明如下:

char ch = 'a';
char *cp = &ch;

下面看看具体的指针表达式相关内容:(关于表达式左右值,参见:第四章 语句&第五章 操作符和表达式
    1)、&ch:代表刚才声明的字符‘a’的地址,所用它可以作为表达式的右值;但是,由于这个地址是编译器分配的,程序员无法知道它的具体地址,所以不能作为表达式的左值。
    2)、cp:作为右值,cp代表指针变量cp指向的ch的地址;作为左值,cp代表指针变量的内容。所以对于指针变量cp来说,作为表达式的左右值均可。
    3)、&cp:与&ch类型,不过这个代表指针变量的地址。这个结果的类型是指向字符指针的指针。同样,这个值的存储位置并未清晰定义,所以这是一个不合法的左值。
    4)、*cp:这个表达是指针的间接访问操作。作为右值,它的值为字符‘a’;作为左值,就相当于变量ch。
下面介绍点稍难的表达式:
    5)、*cp+1:首先,‘*’的优先级高于‘+’,所以先执行间接访问操作,其值为‘a’+1,为‘b’。这个表达式的最终存储位置是不明确的,所以不能够作为左值。
    6)、*(cp+1):和上一个相似,但有本质区别:因为“()”的原因,这个表达式首先计算cp+1,即ch变量的后一个地址,这个地址的值是什么?不知道!但是作为右值,它是合法的。现在来看看这个表达式能不能作为左值:尽管cp+1本身是非法的左值,但是执行了间接访问操作,这个含义与*cp是类似的,所以作为左值是合法的。
    7)、++cp:这个和cp+1有啥区别?看看第四章 语句&第五章 操作符和表达式。那么作为右值,它代表什么:它指向字符变量ch的后一个地址。但是其存储位置不明确,是非法的左值。
    8)、cp++:这玩意和++cpp又有啥区别?简单:前缀++先增加它的操作数再返回这个结果,而后缀++是先返回cp值的拷贝然后在增加cp的值。所以作为右值,它表示指向ch的字符指针,即‘a’;和上一个例子一样,作为左值它是非法的。
    9)、*++cp:这里,间接访问操作符作用于增值后的指针拷贝上,所以它的右值是ch后面的那个内存地址,而它的左值就位于那个位置本身。
   10)、*cp++:使用后缀++操作符所产生的结果不同,他的右值和左值分别是变量ch的值和ch的内存位置,而cp则指向了ch后一个内存位置。事实上,这里涉及3个步骤:a、++操作符产生cp的一个拷贝,b、++操作符增加cp的值,c、在cp的拷贝上执行间接访问操作。
   11)、++*cp:在这个表达式中,由于这两个操作符的结合性都是从右向左,所以首先执行的是间接访问操作,然后cp所指向的位置的值增加1,表达式的结果是这个增值后的值的一份拷贝。
   12)、(*cp)++:使用后缀++操作符,必须加上括号,使它首先执行间接访问操作。这个表达式与前一个相似,但是它的结果值是ch增值前的原先值。
看明白了?再来点恶心的~~~
   13)、++*++cp:诡异吗?很诡异!但如果上面12个你都弄明白的话,这个不是很复杂:这个表达式有3个操作符,都是从右向左结合的。所以先执行++cp,执行后cp指向ch后一个内存地址;再指向间接访问,即cp指向地址存的值,是多少?鬼知道!但是合法!最后计算前缀++,表达式的结果为鬼知道的值加1。当然了,作为左值是非法的。
   14)、++*cp++:这个和上一个的区别在于第一个++操作符是后缀形式而不是前缀形式。由于它的优先级高,所以先执行它。间接访问操作所访问的是cp所指向的位置而不是cp所指向的后面那个位置。

6、指针运算:当指针和整数量进行计算时,整数在执行运算前会根据合适的大小进行调整。
    1)算术运算(加减运算)
        指针和整数间的运算,如:

float values[NUMBER]
float *vp;

for(vp = &values[0];vp < &values[NUMBER];)
    *vp++ = 0;

        这个例子中的指针运算是用++操作符完成的,每增加1,增加值1都会与float的长度相乘,其结果加到指针vp上。

        指针和指针间的运算:
        如果两个指针都指向同一个数组中的元素,表达式"p1-p2"就是合法的。表达式的值为(p1地址值-p2地址值)/数组类型长度。
    
    2)关系运算(< <= > >=)原理同算术运算,不再赘述。
           
阅读(1221) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~