指针的基础概念(c语言)

指针基础知识点:
一、 指针是什么?
二、 指针和指针类型
三、 指针运算:
四、指针和数组
五、二级指针
六、指针数组
一、 指针是什么?
1.指针变量是变量,指针是地址。
2.指针就是变量,用来存放地址的变量。
(存放在指针中的值都被当成地址处理)
3.指针是用来存放地址的,地址是唯一标示地址空间的。
4.不管什么样的指针,指针的大小在32位平台是4个字节,在64位平台是8个字节。
二、 指针和指针类型:
1.指针的定义方式:type *
(char *类型的指针就是存放char类型的变量的地址,
int * 类型的指针就是存放int类型的变量的地址…)
2.指针的解引用:
指针的类型决定了,对指针解引用的时候有多大权限(能操作几个字节)
(比如:char * 的 指针解引用就只能访问一个字节,
int * 的指针解引用就能访问四个字节。…)
三、 指针运算:
1.指针±整数:
指针+1,其加上其指向类型的大小。
2.指针-指针:
两指针相减指两指针中间所经历元素的个数。
(元素由两指针类型决定)
3. 指针的关系运算:
允许指向数组元素的指针与指向数组最后一个元素
后面的那个内存位置的指针 相比较,但是不允许于
与指向第一个元素之前的那个内存位置的指针比较。
四、指针和数组
(指针和数组没有关系,进行数组元素访问时有相似的性质)
数组名表示的是数组首元素的地址。
(两种特例:sizeof(数组名),&数组名
数组名表示的是整个数组。)

五、二级指针
1.二级指针存放的是一级指针变量的地址。
2.二级指针以上+1就是+4.
六、指针数组
1.指针数组时数组, 存放指针的数组。
2.是指针还是数组由相关的操作符优先级确定。

//《C语言深度剖析》指针章节
4.3.1,以指针的形式访问和以下标的形式访问
下面我们就详细讨论讨论它们之间似是而非的一些特点。例如,函数内部有如下定义:
A),char*p = “abcdef”;
B),chara[]= “123456”;
4.3.1.1,以指针的形式访问和以下标的形式访问指针
例子 A)定义了一个指针变量 p,p 本身在栈上占 4 个 byte,p 里存储的是一块内存的首 地址。这块内存在静态区,其空间大小为 7 个 byte,这块内存也没有名字。对这块内存的访 问完全是匿名的访问。比如现在需要读取字符‘e’,我们有两种方式:
1)以指针的形式:*(p+4)
先取出 p 里存储的地址值,假设为 0x0000FF00,
然后加 上 4 个字符的偏移量,得到新的地址 0x0000FF04。
然后取出 0x0000FF04 地址上的值。
2)以下标的形式:p[4]。
编译器总是把以下标的形式的操作解析为以指针的形式的操 作。
p[4]这个操作会被解析成:先取出 p 里存储的地址值,
然后加上中括号中 4 个元素的偏 移量,计算出新的地址,
然后从新的地址中取出值。

也就是说以下标的形式访问在本质上 与以指针的形式访问没有区别,只是写法上不同罢了。

4.3.1.2,以指针的形式访问和以下标的形式访问数组
例子 B)定义了一个数组 a,a 拥有 7 个 char 类型的元素,其空间大小为 7。数组 a 本身 在栈上面。对 a 的元素的访问必须先根据数组的名字 a 找到数组首元素的首地址,然后根据 偏移量找到相应的值。这是一种典型的“具名+匿名”访问。比如现在需要读取字符‘5’
我们有两种方式:
1)以指针的形式:*(a+4)。
a 这时候代表的是数组首元素的首地址,假设为 0x0000FF00,
然后加上 4 个字符的偏移量,得到新的地址 0x0000FF04。
然后取出 0x0000FF04 地址上的 值。
2)以下标的形式:a[4]。
编译器总是把以下标的形式的操作解析为以指针的形式的操 作。
a[4]这个操作会被解析成:a 作为数组首元素的首地址,
然后加上中括号中 4 个元素的 偏移量,计算出新的地址,
然后从新的地址中取出值。

由上面的分析,我们可以看到,指针和数组根本就是两个完全不一样的东西。
只是它们 都可以“以指针形式”或“以下标形式”进行访问。
一个是完全的匿名访问,一个是典型 的具名+匿名访问。
一定要注意的是这个“以 XXX 的形式的访问”这种表达方式。

另外一个需要强调的是:上面所说的偏移量 4 代表的是 4 个元素,
而不是 4 个 byte。只不过这里刚好是 char 类型数据 1 个字符的大小就为 1 个 byte。记住这个偏移量的单位是元 素的个数而不是 byte 数,在计算新地址时千万别弄错了。
·······································································

4.3.2 a 和&a 的区别
通过上面的分析,相信你已经明白数组和指针的访问方式了,下面再看这个例子:

main() //主要是考查关于指针加减操作的理解
{ 
inta[5]={1,2,3,4,5};
 int*ptr=(int*)(&a+1); 
 printf("%d,%d",*(a+1),*(ptr-1)); //2 5
 }

对指针进行加 1 操作,得到的是下一个元素的地址,
而不是原有地址值直接加 1。
( 一个类型为 T 的指针的移动,以 sizeof(T) 为移动单位)
解析:
对上题来说,a 是一个一 维数组,数组中有 5 个元素;
ptr 是一个 int 型的指针。
&a +1: 取数组 a 的首地址,该地址的值加上 sizeof(a) 的值,
&a +5*sizeof(int)也就是下一个数组的首地址,
显然当前指针已经越过了数组的界限。
(int*)(&a+1) : 则是把上一步计算出来的地址,
强制转换为 int* 类型,赋值给 ptr。
*(a+1) : a,&a 的值是一样的,但意思不一样,
a 是数组首元素的首地址,也就是 a[0]的首地址,
&a 是数组的首地址,a+1 是数组下一元素的首地址,
即 a[1]的首地址,&a+1 是下一 个数组的首地址。
所以输出 *(ptr-1): 因为 ptr 是指向 a[5],并且 ptr 是 int* 类型,
所以 *(ptr-1) 是指向 a[4] ,输出 5。

猜你喜欢

转载自blog.csdn.net/unique_IT/article/details/92762083
今日推荐