Chinaunix首页 | 论坛 | 博客
  • 博客访问: 71009
  • 博文数量: 25
  • 博客积分: 880
  • 博客等级: 准尉
  • 技术积分: 245
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-05 10:27
文章分类

全部博文(25)

文章存档

2011年(1)

2009年(2)

2008年(22)

我的朋友

分类: C/C++

2008-08-21 11:28:35

参考书目:

《高质量C/C++

《程序员面试宝典》.

C专家编程》

(一)指针:

1)关于初始化:

不管指针是全局的还是局部的,静态的还是非静态的,应当在声明它的同时初始化它,要么赋予一个有效的地址,要么赋予它NULL。这是一种一捆子打死的办法很好,不必多操心。事实上全局指针变量的默认值为NULL,理论上可以不必初始化。

2)“*”符号的右结合性:

例子:int *abc仅仅是把a定义为了指针变量,而变量bc都是整型。

(3)编译器把指针值解释为unsigned int类型

(4)void * 类型的指针变量不能进行算术运算(例如:p++p+i之类),只能进行赋值、比较、sizeof()操作。对void * 类型的指针变量使用*来取其所指向的变量。

(二)数组

1如果const和(或)volatile关键字之后紧跟类型说明符(如intlong),那么它作用于类型说明符,在其他情况const和(或)volatile关键字作用于它左边紧邻的指针星号。

数组名是什么变量。

       int const *A;  //A可变,*A不可变  ???

int *const A;  //A不可变,*A可变  int类型的常量指针。

数组名是一个常量指针。

(2)标准C/C++不会对用户访问数组是否越界进行任何检查,无论是静态的(编译时)还是动态的(运行时)检查。

    事实上数组的元素个数的信息保存在某个地方,一半是数组首元素之前的那个地址,地址为a-sizeofint,也就是占用一个int变量的字节数,你可以去检查数组数组是否越界,不过每次访问数组中的元素都去进行检查的话,这运行时开销得多大!另外,C/C++还允许同类型的指针访问数组元素,那么指针访问是否越界又怎样知道呢?指针除了类型和它的值外,嘛都没有,所以是无法控制了,所以就干脆不做检查了。程序员必须注意这个问题。

3)数组作函数形参:

“作为函数参数的数组名”等同于指针——《C专家编程》

把数组作为参数传递给函数时,并非把整个数组传递进去,此时数组退化为一个同类型的指针——《高质量C/C++

为什么这么做?

a)数组在内存中连续存放,只传递数组名指针也可以访问整个数组。

b)全部传递开销太大,如果把整个数组元素都传递进去,不仅需要大量的时间拷贝数组,也将占用大量的堆栈空间,我们知道堆栈空间是有限的。

4)数组的删除:

int *a = new char[1024];

delete []a; 

这个必须是一一对应的。如果使用delete a;来释放是不行的,这样释放只是释放了数组名所占的那点内存空间。关于C/C++为什么在释放数组是为什么采取delete []p的形式,是因为语言本身做了一次妥协,如果都采用delete p;的形式的话,也是可以删除数组内存的,首先编译器去读取数组的大小,再全部遍历,删除所有数组所占内存空间,可以,完全可以,不过要是p就是个指针呢,你费这大劲去删除,怎样呢,不成功,还可能导致一些不该删除的内存被删除,这样,语言只好做了一次折中,只有看到[]运算符时,才认为是个数组,才去遍历。

多维的:

int *p1[2] = new int[3][2];

delete []p1;

char (*p2)[2][3] = new char[4][2][3];

delete []p2;

多维数组被看成指向数组的指针,而不是等价于一个指向其元素类型的指针。

(三)字符数组,字符串,字符指针

字符数组就是元素为字符的数组,字符串就是结尾为’\0’的字符数组,看见,字符数组不一定是字符串。

对于字符串来说,他是可变长的,因此无法记住其长度,但是因为字符串有一个结尾:\0,所以只需要一个指向其开头字符的指针就可以实现对于所有字符串的引用。

字符数组使知道长度的(数组长度可知,字符串这个特殊的字符数组长度就不可知,因为可变长)。

计算字符串的长度要多考虑一个结束符’\0’;

对于字符串strcout<输出字符串

对于字符指针scout<错误,只能使用:cout<<*s<

字符串的拷贝不可用=“,比较不可用>=”“<=之类。只能用库函数:

strcpy()strcat()这些。

某些字符串函数不自动添加’\0’.

 

()函数指针

在注册一个回调函数的时候,我们常常采用函数指针。C/C++的连接器在连接程序时必须把函数的首地址绑定到对该函数的调用上,因此函数的首地址必须在编译时就确定下来,也就是编译器为函数生成代码的时候,这样的话,函数就是一个编译时常量。

函数指针就是指向函数体的指针,其值就是函数体的首地址,在源代码层面上,函数名就代表函数的首地址。

(五)引用

函数参数和返回值的传递有三种方式:值传递,指针传递,引用传递。

引用的好处:

引用既具有指针的效率,又具有变量使用的方便性与直观性。

()指针与数组可以互换的情形《C专家编程》

1)用a[i]这样的形式对数组进行访问始终都是被编译器改写为*(a+i)这样的指针进行访问。

(2)指针始终都是指针,他绝不可能改写为数组。你可以用下标的方式访问指针,一般都是作为函数参数时,而且你知道实际传递给函数的是一个数组。

(3)在特定的上下文中,也就是作为函数的参数(也只有这种情况),一个数组的声明看作一个指针,作为函数参数的数组(就是在一个函数调用中)始终会被编译器修改为指向数组第一个元素的指针。——这个很重要。

4)因此把一个数组作为函数的参数时,可以定义为数组也可以定义为指针,在函数内部事实上获得的就是一个指针。

5)在其他所有情况下,定义和声明必须匹配,如果定义为一个数组,在其他文件对它进行声明时也必须声明为数组,指针也是如此。

阅读(2147) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~