打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
关于C指针
C语言中学会了指针你也就学会了C语言。但是很多人不能理解指针。
下面摘自百度百科:

大家都认为,c语言之所以强大,以及其自由性,体现在其灵活的指针运用上。因此,说指针是c语言的灵魂,一点都不为过。同时,这种说法也让很多人产生误解,似乎只有C语言的指针才能算指针。basic不支持指针,在此不论。其实,pascal语言本身也是支持指针的。从最初的pascal发展至今的objectpascal,可以说在指针运用上,丝毫不会逊色于c语言的指针。

首先我们来看看NULL的定义:

#ifdef __cplusplus

#define NULL    0

#else

#define NULL    ((void *)0)

#endif

NULLC++中的定义就是0,在C中的定义是(void *0,本质上还是0;指针的值说白了就是一个数字,这个数字存在一个变量中,这个变量就称为指针。

那么说随便一个数字都行吗?肯定不是。这个数字是用来表示内存单元的,因此它必须是合法的内存地址,不管在什么系统上它的值在ULONG(unsigned long)范围内,ULONG32位系统上是0-0xFFFFFFFF,在64位系统上就是0-0xFFFFFFFFFFFFFFFF;也就是说ULONG根据运行环境改变。

32位操作系统为例,在操作系统加载的时候要接管内存,那么它怎么管理呢?就是给每个内存单元编号,这个编号是一个ULONG类型的整数,所以它只能从0编号到0xFFFFFFFF,在普通PC上最小寻址单元是Byte(字节),也就是最多可以编号0x100000000个字节=4GB,这也就是为什么大于4G内存的电脑都需要安装64位操作系统的原因,32位操作系统最高支持4G内存,超出部分无法编号,操作系统也就不能管理,因此不能被使用。

注:以下为32位系统

         C语言中指针就是一个编号,不管什么类型的指针都是以个ULONG类型的整数。那么你不禁要问,为什么我们在定义指针的时候还要指定类型?

举个例子:

  1. void IncreaseInt(int *pi)  
  2. {  
  3.     (*pi) += 256;  
  4. }  
  5. void IncreaseChar(char *pc)  
  6. {  
  7.     (*pc)++;  
  8. }  
  9. int main()  
  10. {  
  11.     int a = 0;  
  12.     char b = 'A';  
  13.     IncreaseInt(&a);  
  14.     printf("%d\n", a);  
  15.     IncreaseChar(&b);  
  16.     printf("%c\n", b);  
  17.     getchar();  
  18.     return 0;  
  19. }  

         在函数IncreasInt中我们使用了“*”运算符,*运算符就是我们从内存的位置取出值。假设变量a的地址是0x1000,传到函数IncreasIntpi的值就是0x1000,我们使用“*”就可以从内存的0x1000处取往后4个字节,加上256后放进0x1000-0x1003在函数IncreasChar中我们也使用了“*”运算符,假设b的地址是0xffc,传到函数IncreasCharpc的值就是0xffc,我们使用“*”就可以从内存的0xffc处取1个字节,自增之后放进0xffc里。

         那么编译器怎么知道“*”要取几个字节,这就是指针类型的作用了,指针类型就是告诉编译器这个指针指向的目标占用的内存是多大,使用*[]的时候才知道要取几个字节。

—————————————————割了—————————————————

  最近项目太忙,把这个给忘了,七夕闲着没事,给补上。

  不管数据在硬盘还是内存中,数据的都是以二进制的方式存在的,比如有一块存储空间的数据是:00010100000100000000000000000000,在工具中为了方便一般使用16进制:41 01 00 00;X86的计算机都是按照小端存储的(什么是小端存储自行百度),这个数据如果使用int类型就是0x141即321,如果使用char是0x41,只取出来第一个字节,不管什么类型来表示数据都是不变的,其实本质上他们是同一块数据。指针表示的就是某块内存的地址。也就是说如果上述存储空间是内存,地址是0x1000,那么如果是int* p = 0x1000,那么*p的值就是0x141,如果是char*  p = 0x1000, *p的值就是0x41。
  从上面的讲述中大家可以明白,内存中存储数据跟类型无关,它不考虑你是什么类型,只有程序才去考虑类型;因为同样一块数据使用不同类型取出的值一样,比如0xffffffff,使用unsigned int 取值是4294967295,使用int取值是-1,使用unsigned char 取值是255(0xff),下面有个例子:

  1. int main()  
  2. {  
  3.  int a = 0;  
  4.  int b[2];  
  5.  b[2] = 10;  
  6.  printf("%d\n", a);  
  7.  return 0;  
  8. }  
   请问输出的值是多少?
   
应该有相当一部分人认为会输出0,认为是10并且知道原因的请绕道,本文不适合你。
不知道结果的继续往下看,我先不说答案:
简单划一下函数的栈内存示意图:
假设main函数基址为bp 

                    参数空间(本例无参)
main函数基址 ----------------------------------------------- bp 
                    a的地址即&a为bp-4
                    b[1]的地址bp-8
                    b[0]的地址bp-12

假设int* p = b;
那么&b[0] = p, &b[1] = p + 1,
以此类推b[2] = p + 2 ,那么字节偏移就是:p = &b[0] = bp - 12,那么p + 2就是bp - 4,即a;
惊奇的发现b[2]就是a,所以本例输出的结果是10。
能把这题看透彻,指针应该学的不会太差。


就写这些了,不写不知道,一写发现真难,举例子很难举。 
QQ909049038
 
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
高质量C/C++编程(片段)
delete与delete [] 真正区别
用C语言来实现的类似C++函数的重载特性
vs c++调用函数后,指针地址被子函数改变了 在内存窗口粘贴变量名
指针数组,数组指针,指针函数,函数指针,二级指针详解
MTK优美代码赏析8可变参数的C函数
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服