各种指针分类总结 + 指针间的赋值关系

一般指针、指针常量、常量指针、z
摘要由CSDN通过智能技术生成

有参考学习其它的,参考学习的来源如下:

http://blog.csdn.net/porscheyin/article/details/3461670

http://blog.csdn.net/lllazy520/article/details/7329635

深入理解void类型 指针与数组的"爱恨情仇"使用指针时的”陷阱“


指针的赋值

指针的地址在内存中存储是是以数值的方式存储的,但这就并不代表指针或者说是地址就没有类型,只能说是它存储的时候本质是以没有类型来存储的,因为实质上内存空间上的内容在存储的时候都是没有类型的,但它读取时是有类型的,所以将一个非0数值赋予一个指针的操作时错的,必须要将这个数组进行(指针类型)的强制转换后,变成一个有类型的地址后才可以进行指针的赋值,这样通过指针进行间接访问和赋值时才知道要操作多大的空间,不过0和NULL就不用了,因为它本身就被系统宏定义为void *类型了,而void *类型能自动转换为各种类型,但注意非0数字并不是void *,所以还要对非0数字进行地址类型的赋予,如下:

#define (void *)0  NULL即为系统为NULL定义的宏定义

int *p = 0; 正确

int *p = 2-2; 正确

int *p = 0x0000; 正确         

 int *p = (int *)0x0000; 正确

因为以上都为0;

int *p = 258; 错误 int *p = (int *)258; 正确

int *p = 0x11010110; 错误int *p = (int *)0x11010110; 正确

int *p = NULL; 正确

char *cp = “abcdefg”;正确

野指针赋为NULL

ANSI C定义了零指针常量(即 NULL)的概念:一个具有0值的整形常量表达式,或者0值表达式被强制转换为void *类型,则称为空指针常量,它可以用来初始化或赋给任何类型的指针(即NULL指针)。也就是说,我们可以将00L'/0'2–20*5以及(void*)0赋给一个任何类型的指针,此后这个指针就成为一个空指针,由系统保证空指针不指向任何对象或函数。ANSI C为此定义了一个NULL,用来表示空指针常量,但不能对NULL指针进行解引用(*p)——会报错!——如此就保证了不会对野指针进行操作,因为在对任何被赋值为NULL的指针进行解引用时一定会报错!!!——所以一定要将野指针赋值为NULL,以避免误用!不过char *p = NULL;if(p)、if(!p)、while(p)、while(!p)是可以的。效果if(p == NULL)、if(p != NULL)、while(p == NULL)、while(p != NULL)一样的!,因为NULL的值就是0


NULL ----- (void*)0

NUL ------   ' \0 '  (ASCII 码表中定义的就是NUL)

nul    ------    不存在,没有定义这个东西


void *型指针作为一种通用的指针,可以和其它任何类型的指针(函数指针除外)相互转化而不需要类型强制转换,但不能对void *指针进行解引用及下标操作(因为无类型大小,无法访问!);



//指向const对象的一般指针---是不允许的 !所以====绝不存在指向const 变量的一般指针,因为不能将const 变量的地址赋给一般指针!!!!!

//指向常量的指针只能是指向字符串常量的指针,而不能是指向const 的指针。

//---------即:指向常量的一般指针存在,但只能是指向常量字符串的char *指针,而指向const常量的一般指针根本就不可能出现!




一般指针、

野指针、

NULL指针(以上有述)、

函数返回指针、


指针常量、有的书上又称为常指针)--------不可改变指向
常量指针---------操作权限受限,仅能“读”的指针,不可对指向对象的内容进行写

指向常量的指针-------指针变量,指向可变,只是指向的是常量,不可使用指针对常量的内容进行改变
字符串常量(出现在表达式中,除了sizeof ,& ,给数组初始化的情况,其它的都可以看成是一个地址——第一个字符的地址)、


指向数组元素的指针、
数组名、

指向数组的指针(数组指针)、

(二维数组名 与 指向数组的指针 和 指向指针的指针不同 !!)、

malloc、


函数名、
函数指针、

函数指针数组、


各种指针间的赋值关系

====================================================================================================================================

(1)野指针 ----------- 要防止它出现 !

指向了不确定的内存区域的指针,通常对这种指针进行操作会使程序发生不可预知的错误。

防止出现野指针必须要做到三大点:-----原理:对野指针乱指的不确定空间被误用是无法察觉的,反而是对NULL进行解引用的话编译器会发出报错!

1在声明指针时将其初始化为NULL或零指针常量------ 防止其乱指,指向的不确定空间被误用了而无法察觉

2free一个指针后,一定要将这个指针设置为NULL或零指针常量,除非能保证后面对这个free的指针不再使用,但及时对一个未指向的指针赋值NULL是一个良好的习惯!------在释放完指向的空间后,指针变成野指针,防止误用其乱指的空间而无法察觉


(1.5)函数返回指针---------- 要保证返回 的地址上的空间内容没有被释放,保证是值传递,只要空间内容还在,那么传递的这个地址就是 有效的。

3函数返回指针时,只能返回静态局部变量的地址、或函数malloc分配的指针、或传递的形参指针,只要保证返回的这个指针所指向的空间没被(手动、自动)释放、这个指向的地址空间的内容值还有效就行。------ 函数返回的地址是存在的,但是当函数返回之后,函数内部的空间就会自动释放,返回的地址仍存在,但是地址上存储的空间内容却被隐形释放了,这就会导致我们在对返回的地址进行解引用时还误以为此地址上的空间内容还存在,对获得的内容其实已经是不确定的无效值了还不自知,而这个也是编译器无法察觉的。所以对函数返回指针时一定要严加注意,一定要保证返回的指针所指向的空间还是有效的。


(2)指针常量---------- 只是指向被限制了而已 !,在定义时要马上初始化

int a = 6;

int * const p1= &a;//指针常量在定义时要马上初始化

int *const p2;//错误!!!因为不可再重新赋值了,此时给它初始化的值是一个不确定的随机无效值!

只是这个指针被声明为常量了,但它指向的空间内容并没有指为常量,所以可以对其指向的空间内容做变化,不能变的只是此指针的指向,一但初始化了就不能在赋予其其它的指针了,所以说在定义时就一定要用我们想要的地址值去初始化它有多必要。

但是要注意的是:但数组名并不是一个指针常量 ,只是可以看做一个指针常量!!!------- (具体可看(5)数组名的解释)


(3)常量指针 ----------- 只是其对指向的空间的操作权限(修改内容的权限)被限制了而已(只能访问,不能修改) !

const int * p1;//这两种定义方式都可以(只要在 * 的前面就可以了) !

  int const * p2;

常量指针可以指向任何地址,也可以对它进行重定向(其指针的值可以被重新赋值),但无法通过对常量指针的解引用(*p 或p[] )来对其指向的地址空间内容进行修改,只能有访问的权限。但其指向的空间内容本身是什么就是什么,不受常量指针的影响,该可改就可改(非const变量),该不可改就不可改(const变量) !

常量指针常用于函数间的指针参数传递,以防止在函数内部对指针指向的内容进行修改,用常量指针作为形参,用一般指针作为实参,可以起到函数内部对传递的空间内容只有访问权限,从而保护了传递的地址空间内容,如 int strcmp(const char * str1 , const char * str2) 就是如此用法,即完成了比较,防止了被修改的隐患!

另外,常会对字符串常量返回的指针误以为是常量指针,但根据指针间的赋值原则来看,由char * s = "abcd"; 可得“abcd"返回的指针只能是char * 型一般指针,也就是说字符串常量在表达式中返回的指针仅仅只是一个指向字符常量的一般字符指针,而不是什么常量指针!


(4)字符串常量

在静态存储区分配地址空间,并且会返回一个指向字符的地址

当用在表达式中时,除了一下三种情况:sizeof(”abcd“),&"abcd"(返回的是第一个字符的地址,这里的“abcd”仅当做字符来解释) ,给字符数组赋值char a[] = "abcd")时,其它情况下字符串常量"abde.."都可以当做一个指针处理,且是一个指向字符(指向字符串常量第一个字符)的一般指针,无法通过此常量指针对字符串常量的内容进行修改,此常量指针指向字符串常量的第一个字符。

常会对字符串常量返回的指针误以为是常量指针,但常量指针的定义表示式是const char *p,而根据指针间的赋值原则来看,由char * s = "abcd"; 可得“abcd"返回的指针只能是char * 型一般指针,也就是说字符串常量在表达式中返回的指针仅仅只是一个指向字符的一般指针(其实就只是静态分配区中的一个地址而已),而不是什么常量指针,字符串常量返回的确实是一个指向常量的一般指针,但却是指向一个字符串常量的首字符的指针,而不是指向const常量的指针而不是常量指针。不过倒时可以说字符串常量返回的指针是一个“指向常量的指针常量”,其实它并不是什么指针,就是一个常量取的地址而已,然后赋值给一般指针 char * , 而char *却不是指针常量,它只是一个普通指针,还可以改变指向的。要记得指向常量的一般指针存在,但只能是指向常量字符串的char *指针,而指向const常量的一般指针根本就不可能出现!

const char c = 'k'; char * p = &c ;不可能实现。

能实现的只能是:  char c = 'k' ; char *p = &c ; 而这时的'k'不能算是什么常量,只是一个复制的关系,在静态区中‘k’这个常量还不存在。

char s[] = "abcde"; //只是将字符串"abcde"赋给数组s的地址空间上,而字符串常量”abcde“从始至终都不存在,这里的”abcde“只是作为单纯的一个字符串,与字符串常量没关系,更谈不上返回一个常量指针了;

char *p = "abcdef";

printf(”%c“,*p); // 'a'

printf(”%c“,p[3]); // 'd'

  • 7
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值