1.28——指针

1.野指针可能带来哪些后果?

野指针,即指向一个错误位置的指针,如果你的程序中有野指针,你的数据就危险了。存放在堆中的数据可能会被破坏,用来处理堆的数据结构也可能被破坏,甚至操作系统的数据也可能被修改,甚至有时上述三种破坏情况同时发生。

此后可能发生的事情取决与这样两点:第一,内存中的数据被破坏的程度有多大;第二,内存中的被破坏的部分还要被使用多少次。在有些情况下,一些函数将立即无法正常工作;在另一些情况下,程序会终止并报告一条出错消息,或者程序可能会挂起,或者程序可能会陷入死循环,或者程序可能会产生错误的结果,或者程序看上去仍然正常运行,因为程序没遭到本质的破坏。

 

2.常量指针与指针常量

 

(1) const char *p;
(2) char* const p;
(3) char *p = "abc";

语句(1)第一了一个常量指针,即指向一个常量的指针,指向的内容是常量,不可以修改,放在常量区的,但指针本身可以修改,即“*p=‘b’”是非法的,*p是p指向的常量的第一个字符,是个常量,不能改变的。“p=&q”这是可以的,指针可以指向不同的地址。

语句(2)定义了一个指针常量,即指针本身是个常量,不可修改,但指针指向的内容可以修改,一开始定义时让它指向数组a,“*p=‘b’”这是可一个,但“p=&b”是非法的。

const常量*指针,当const在*之前就是常量指针,而const在*之后就是指针常量。例如“const char*p”即char*p是个常量,所以内容是常量;“char* const p;”即指针p是个常量。

语句(3)中“char *p”定义的是一个指针变量p,指向字符串abc首地址。这里特别要注意,在C语言中,(3)中定义的是一个常量字符串,它被放在静态存储区的常量区存储,而p是一个指针变量,放在栈上。如果“*p=‘b’”在编译时能通过,但在运行时就会出现错误,因为你识图去改变常量区的内容。

 

3.空指针的三种用法

(1)用空指针终止对递归数据结构的间接引用。

(2)用空指针进行函数调用失败时的返回值。

(3)用空指针作警戒值。

 

4.指针数组和数组指针

指针数组“typename *p[n]”定义了一个数组,数组包含了n个指针变量p[0],p[1],…,p[n-1]。符合一般数组的特性,除了数组中的元素是指针以外,和一般的数组没什么区别。数组名p是个指针常量,不能直接进行指针运算,不过可以传递给函数来进行。可以通过“p[x]”来对指针数组进行赋值,如“p[2] = "hijklm";”,否则,对数组中的每个指针进行初始化,必须先分配p[x]锁指向的内存空间!必须对分配结果进行判断。

指向数组的指针(以二维数组为例),二维数组“int[2][4]”,可以看作有两个num[4]的数组构成,数组名指向第一个元素,num[0]指向{num[0][0],num[0][1],,,num[0][3]},num=num[0]=&num[0][0];num+1=num[1]=&num[1][0];二维数组名可以看做一个指向指针数组的指针。

 

5.指针函数和函数指针

(1)函数指针:即指向这个函数的指针,定义为“数据类型(*fun)(参数列表);”,()的优先级比*高,所以*fun加括号,如"void (*fun)(int *,int*);";

(2)指针函数:即返回值是指针的函数,定义为“数据类型 *fun(参数列表);”,如“char *fun(int*, int*);”,即返回值为char* 型。

 

6.指针函数的返回值问题

当函数的返回值为指针类型时,应该尽量不要返回局部变量的指针,因为局部变量是定义在函数内部,当这个函数调用结束了,局部变量的栈内存也被释放了,因此不能够正确地得到返回值。实际上,内存已经被释放了,但这个指针的地址已经返回过去了,但是这个地址已经是无效的了,此时,对这个指针的使用是很危险的。

 

7.左右法则

右左法则:首先从最里面的圆括号内未定义的标识符开始阅读看起,然后往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。一旦解析完圆括号里面所有的东西,就跳出圆括号。重复这个过程直到整个声明解析完毕。

在通过复杂例子解析左右结构之前,我先说一下指针数组嵌套中的一些基本类型

1.int a;  整形变量
2.int *a; 整形指针变量 
3.int **a; 整形指针的指针变量(一个指向指针的指针,它指向的指针指向一个整形数)
4.int a[10];  整形数组
5.int  *a[10]; 整形指针数组(一个数组中有10个指针,该指针指向一个整形数)
6.int (*a)[10]; 整形数组指针(一个指向有10个整形数组的指针)
7.int (*a)(int); 函数指针变量(一个指向函数的指针,该函数有一个整形参数并返回一个整形数)
8.int (*a[10])(int); 函数指针数组(一个有10个指针的数组,该指针指向一个函数,该函数有一个整形参数并返回一个整形数)

介绍完一些基本类型,下面来介绍一些复杂的例子

1.int *( * ( *fpl ) ( int ) ) [10];
--*fpl   知道fpl是一个指针
--*(*fpl)(int)  知道指针fpl指向一个形参为int,返回值为指针的函数
--int *(*(*fpl)(int))[10]  知道该函数的指针指向一个数组,该数组有10个元素,并且每个元素指向一个整数

总结:fpl被声明为一个函数的指针,该函数返回值是一个指向指针数组的指针。

8.字符串函数

 

1. strcpy

原型:char *strcpy (char * __dest, const char * __src); 
功能:将一个字符串(__src)拷贝到另一个字符串缓冲区中(__dest),并返回拷贝后的字符串指针; 

2. strncpy

原型:char *strncpy (char * __dest, const char *__src, size_t __n); 
功能:将一个字符串(__src)拷贝到另一个字符串缓冲区中(__dest),拷贝最多不超过__n字节,并返回拷贝后的字符串指针;

3. strcat

原型:char *strcat (char *__dest, const char *__src); 
功能:将一个字符串(__src)拼接到另一个字符串缓冲区中(__dest),并返回拼接后的字符串指针;

4. strncat

原型:char *strncat (char *__dest, const char *__src, size_t __n); 
功能:将一个字符串(__src)拼接到另一个字符串缓冲区中(__dest),最多不超过__n个字节,并返回拼接后的字符串指针

5. strlen

原型:size_t strlen (const char *__s); 
功能:返回一个字符串(__src)的长度,即字节(符)数,这里仅考虑ASCII字符;

6. strcmp

原型: int strcmp (const char *__s1, const char *__s2); 
功能:比较字符串__s1和字符串__s2,返回比较结果,如果相等,则返回0; 
比较方式:两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇’\0’为止; 
返回结果:当s1<s2时,返回值<0;当s1=s2时,返回值=0;当s1>s2时,返回值>0; 

7. strncmp

原型: int strncmp (const char *__s1, const char *__s2, size_t __n); 
功能:比较字符串__s1和字符串__s2__n个字符,返回比较结果,如果相等,则返回0; 
比较方式:同strcmp; 
返回结果:同strcmp; 

8. strcasecmp

原型: int strcasecmp (const char *__s1, const char *__s2); 
功能:比较字符串__s1和字符串__s2,忽略大小写的比较,返回比较结果,如果相等,则返回0; 

9. strncasecmp

原型: int strncasecmp (const char *__s1, const char *__s2, size_t __n); 
功能:比较字符串__s1和字符串__s2__n个字符,忽略大小写的比较,返回比较结果,如果相等,则返回0; 

9.万能指针void

void指针一般成为通用指针或泛指针,它是C语言关于“纯粹地址”的一种约定。void指针指向某个对象,但该对象不属于任何类型。在C语言中,任何时候都可以用其他类型的指针来代替void指针,或者用void指针来代替其他类型的指针,并且不要进行强制类型转换。当进行纯粹的内存操作时,或者传递一个未定类型的指针时,可以使用void指针。void指针也经常用作函数指针。
 
10.NULL终是被定义为0吗,总是等于0吗?
NULL不是被定义为0,就是被定义为(void *)0,这两种值几乎是相同的。当程序中需要一个指针是(尽管编译程序并不是总能只是什么时候需要一个指针),一个纯粹的0和或一个void指针都能自动被转换成所需的任何类型的指针。
假如是指“与比较的结果为相等”,那么NULL确实再试等于0,这也就是空指针定义的本质所在。假如是指“其存储方式和整形值相同”,那么答案是不。NULL并不必须被存为一个整形值0,尽管这是NULL最常见的存储方式。在有些计算机中,NULL会被存成另外一些形式。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值