`

C指针的实质,对底层理解很有好处

阅读更多

最近对C/C++指针特别感冒,就详细的研究了下
看下面的定义:
char a[] = "Hello World";
char *p  = "Hello World";
1.什么是地址
地址本身就是一种基本数据类型,它跟整数,浮点数,字符等基本类型是一样的。指针不是类型,真正的类型是地址,指针只不过是存储地址这种数据类型的变量。
打个比方,对于
int i=10;
10是整数,而i是存储整数的变量,指针就好比这个i,地址就好比那个10。指针能够进行加减法,原因并不是因为它是指针,加减法则不是属于指针这种变量的,而是地址这种数据类型的本能,正是因为地址具有加减的能力,所以才使指针作为存放地址的变量能够进行加减运算。这跟整数变量因为整数能够进行加减乘除因而它也能进行加减乘除一个道理。
2.什么是指针
指针本身就是一个变量,它跟其他的变量是一样的。指针本身是一个符号。
比如 int *p,我们定义了一个指针p,编译器就会在内存分配一个2(32位系统是4个字节)字节的存储空间。我们在使用p的时候,p的值就是刚刚所分配的存储空间中所存的内容。再来看看变量,我们定义int a = 10,a是一个变量名。我们在使用a的时候,用的是a所对应的存储空间的内容。a本身可以理解为就是一个符号,它跟某个存储空间相对应。&a就是取a所对应的存储空间的地址。这样,指针也是变量,本身也是一个符号,在使用p的时候,我们使用的是p这个变量所对应的存储空间的内容,而这个存储空间的内容有些特别,它不是整数,也不是浮点数,而是一个地址类型的数据。那么&p是什么意义呢,&p就是指p所对应的存储空间的地址(这个地址可不是p所对应的存储空间的内容哦)。那么*p怎么理解呢?记住在使用时,p的值是所对应的存储空间的内容,那么*p自然就是取出那个地址所对应的存储空间的内容了。
3.什么是数组名
数组名:就是一个数,这个数和整数,浮点数类似,是一个地址类型的数据。就像int a = 10;这里的10就是一个整数,它跟地址类型数据属于一个层次。也就是说数组名跟整数10是相似的,而跟a差距大多了,根本不是一个概念.应该说数组名与&a是一样的,都是一个地址数据,同时数组名还是一个常量常量,地址常量。
用来存放数组的区域是一块在栈中静态分配的内存(非static),而数组名是这块内存的代表,它被定义为这块内存的首地址。这就说明了数组名是一个地址,而且,还是一个不可修改的常量,完整地说,就是一个地址常量。数组名跟枚举常量类似,都属于符号常量。数组名这个符号,就代表了那块内存的首地址。注意了!不是数组名这个符号的值是那块内存的首地址,而是数组名这个符号本身就代表了首地址这个地址值,它就是这个地址,这就是数组名属于符号常量的意义所在。由于数组名是一种符号常量,因此它是一个右值,而指针,作为变量,却是一个左值,一个右值永远都不会是左值,那么,数组名永远都不会是指针!
4.再来讨论开头我们所定义的字符数组和字符串指针的区别
我们假定这两个定义是在同一个函数中的(如main)。
继续:*(a+1) =u;
*(p+1) = u
这里第一个操作会通过,而第二个操作则会出现段错误。这是什么原因呢?那么我们需要了解下,程序空间分配中存储区问题。C/C++程序所对应的存储区,分位三类
1.静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间 都存在。它主要存放静态数据、全局数据和常量。
2.栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束 时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
3.堆区:亦称动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或delete释放内存。
这里char a[] = "Hello World",其空间是分配在栈中的,所以你可以对其中的内容进行修改。而char *p = “Hello World”,其空间是分配在静态存储区的。且Hello world为字符串常量,是不允许修改的。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics