C语言-指针
本文最后更新于:1 年前
注意点
指针的加减操作会移动一个数据类型的长度
1
2y = ++*px; //px的内容加上1之后赋给y,++*px相当于++(*px)
y = *px++; //相当于y=*(px++)sizeof(数组名)才能获取数组长度,sizeof(数组指针)得到指针本身长度。sizeof返回无符号数,类型size_t
1
2
3
4
5int a[5]={0};
int *p = a;
sizeof(p)/sizeof(int) --> 1
sizeof(a)/sizeof(int) --> 5
数组名作为函数参数时都是指针
以下三种形式都传递了数组指针,在函数内部无法通过这个指针获得数组长度,都要作为指针变量对待。(数组名退化为一级指针)
1 |
|
空指针应初始化为NULL(注意大小写)
char *str = NULL;
NULL 是在stdio.h中定义的一个宏 #define NULL ((void *)0)
,void *
表示指针指向的数据的类型是未知的,一般在后续使用时进行强制类型转换
用指针作为函数返回值时
需要注意,函数运行结束后会销毁在它内部定义的所有局部数据,包括局部变量、局部数组和形式参数,函数返回的指针请尽量不要指向这些数据
指针数组
1 |
|
输出结果为:
str1 = Programming
str2 = is
c1 = f
c2 = 2
c3 = E
lines[1]
:它是一个指针,指向字符串string1,即string1 的首地址。*(lines + 3)
:lines + 3 为数组中第 3 个元素的地址,*(lines + 3)
为第 3 个元素的值,它是一个指针,指向字符串 string3。*(*(lines + 4)+ 6)
:*(lines + 4) + 6 == lines[4] + 6 == string4 + 6
,表示字符串 string4 中第 6 个字符的地址,即 f 的地址,所以 ((lines + 4) + 6) 就表示字符 f。(*lines +5)[5]
:*lines + 5
为字符串 string0 中第 5 个字符的地址,即 2 的地址,(*lines+5)[5]
等价于*(*lines+5+5)
,表示第10个字符,即 2。*lines[0]+2
:lines[0] 为字符串 string0 中第 0 个字符的地址,即 C 的地址;*lines[0]
也就表示第 0 个字符,即字符 C。字符与整数运算,首先转换为该字符对应的 ASCII 码,然后再运算,所以*lines[0] + 2 = 67 + 2 = 69
,69 对应的字符为 E。
二维数组指针
1 |
|
括号中的*表明 p 是一个指针,它指向一个数组,数组的类型为int[4],这正是 a 所包含的每个一维数组的类型。
[ ]的优先级高于*,( )是必须要加的,如果赤裸裸地写作
int *p[4]
,那么应该理解为int *(p[4])
,p 就成了一个指针数组,而不是二维数组指针p指向数组 a 的开头,也即第 0 行;p+1前进一行,指向第 1 行。
*(p+1)
表示取地址上的数据,也就是整个第 1 行数据。注意是一行数据,是多个数据,不是第 1 行中的第 0 个元素*(p+1)+1
表示第 1 行第 1 个元素的地址。因为*(p+1)
单独使用时表示的是第 1 行数据,放在表达式中会被转换为第 1 行数据的首地址,也就是第 1 行第 0 个元素的地址,因为使用整行数据没有实际的含义,编译器遇到这种情况都会转换为指向该行第 0 个元素的指针;就像一维数组的名字,在定义时或者和 sizeof、& 一起使用时才表示整个数组,出现在表达式中就会被转换为指向数组第 0 个元素的指针。
*(*(p+1)+1)
表示第 1 行第 1 个元素的值。很明显,增加一个 * 表示取地址上的数据。