-
指针的概念
(1) 指针也是一种变量,用来存放其他变量地址的变量,指针的地址也是最开头的地址
(2) int a = 0
int *p = &a (int * 是一种数据类型,所以p 用来存放地址)
*p = 100 等价于 a = 100(因为p指向a)
注意:系统通过变量名或者地址来访问内存
(3)*有两个含义:定义时表示后面的变量是指针;使用时表示取值
(4)无论什么类型的指针都是四个字节
运行结果:4 4 4 4
(5)指针只能指向同类型的变量 :char b = ‘a’
int *p = &b × char *p = &b √
上面这个值得注意:int *p1 = &a ,一个是整型,一个数组型(&a),不兼容,需要加强制转换符(int *)&a -
地址传递
运行结果 :a = 1 b = 2
a和b的值并没有交换,因为函数调用是是在栈空间里面交换a和b的值,交换完释放空间,原函数值不变
只能进行地址传递,用指针来交换值,才能真正的交换,因为指针指向原函数空间
运行结果: a = 2 b = 1
注意:程序中的交换函数用了一个小算法 ,记住 -
指针运算
(1)对于本题先看第一种 不定义y = 0
运行结果:
再看第二种定义y = 0的运行结果:
为什么呢?
首先第二个printf把px指向的值加一 也就是px = 4
再看第三个printf 中 ** px++表示输出px 后把px加一 也就是px指向的地址加一*
最后在第四个printf中,第二种定义了y=0,px的地址等于y的地址,所以输出0;但是如果未定义y=0,px地址加一不知道指向哪里去,所以指向的值也是乱码
(2)利用指针实现库函数strcpy
4. 指针的内存申请(野指针的问题)
char *str ; *str = ‘a’ ×
这是定义了一个野指针 指向了不能使用的内存,所以要想使用空指针就需要申请一个内存
char *str = (char *)malloc (sizeof (char) * 100)
申请了连续的100个字节的堆内存空间,并且返回这段内存的首地址给str(str在栈空间)
注意:使用malloc需要调用头文件“stdlib.h”,另外用完之后需要释放内存free(str),如果不释放,就会内存泄漏
例如用指针实现字符串的逆序:
虽然算法不难,不过我要解释其中几行为什么要这么写
(1)第8行为什么要加个str ?
因为char *end是定义了一个指针,他指向地址,如果单纯写length - 1,肯定不对,因为length - 1是个整型数据,整型数据很明显不能给指针,而加上str就不一样了 str代表地址,地址可以移动,通过加减整数
(2)第22行为什么写个strcpy函数
因为strcpy函数是把变量赋值给str,这样就可以修改str中的值了,下面两种写法来逆序就是错的
char *str = “helloworld”;这种定义可以 ,但是因为字符串是常量,不能改变
char str[32] = “helloworld”;数组名相当于常指针,固定了地址,字符串常量也在内存中有个固定地址,二者不可改变
(3)为什么不在主函数里面完成各个程序,因为比如这个逆序操作,如果放在主函数里面会改变str里面的值,写调用函数的话不会修改。
面试题:
char str1[] = “abc”;
char str2[] = “abc”;
const char str3[] = “abc”;
const char str4[] = “abc”;
const char *str5 = “abc”;
const char *str6 = “abc”;
char *str7 = “abc”;
char *str8 = “abc”;
cout << ( str1 == str2 ) << endl;
cout << ( str3 == str4 ) << endl;
cout << ( str5 == str6 ) << endl;
cout << ( str7 == str8 ) << endl;
结果是:0 0 1 1
解答:str1,str2,str3,str4是数组变量,它们有各自的内存空间;
而str5,str6,str7,str8是指针,它们指向相同的常量区域
- 指针与数组
(1)指针和数组可以相互表示输出
(2)数组和指针又有区别,数组可以赋值,但是野指针不能,因为野指针定位随机,里面盛放的值不确定,所以不能修改里面的值;数组名(包括字符串常量)是常指针,不能修改,因为是系统给分配的固定地址,但是野指针可以指向别的地址
思考题:
输出结果:
解释:比较难理解的是p2中的**(int)a+ 1** ,通过运行发现他代表数组第一个元素的第二个字节(一个整型元素是四个字节),他的值也当然是乱码
6.指针与字符串
运行结果:hello