什么是指针:
1、指针是一种数据类型,使用它可以定义指针变量,简称指针。
2、指针变量中存储的是内存地址(整数,便签的编号),可以通过它访问对应的内存。
3、以32位系统为例,指针变量需要占用4字节内存空间(64系统需要8字节),指针变量的取值范围:0x00000000~0xffffffff,每个整数代表一个字节的内存,指针变量最大可以访问4G内存(64位系统的指针变量则需要占用8字节内存空间)。
4、可以使用printf("%p\n",ptr) 显示指针变量的值。
如何使用指针:
定义指针变量:类型* 指针变量名;
1、指针变量与普通变量的使用方法不同,因此为区别与普通变量,一般指针变量以p结尾。
2、指针变量不能连续定义,一个*只能定义出一个指针变量。
指针变量 int* p1,p2; // p1是,p2普通的int类型变量
int *p1,*p2; // p1,p2都是指针变量
3、指针变量中存储的整数只代表一个字节,当通过指针变量访问内存时,具体访问多少个字节由指针变量的类型决定,也就是说指针变量中存储的是一块内存的首地址。
4、指针变量的默认值与普通变量一样是随机的(野指针),一般为了安全要给指针变量初始化,如果没有合适的内存地址可以先初始化NULL(空指针)。
给指针变量赋值:指针变量 = 内存地址;
// 定义指针变量时初始化
int* p = # // 获取变量的地址赋值给指针变量,num变量的类型要与指针变量相同,否则编译器会产生警告,在解引用时也可能产生段错误
// 定义完指针变量后再赋值
p = malloc(4); // 把堆内存的地址赋值给指针变量,堆内存的使用后续会详细讲解
根据指针变量中存储的内存地址访问内存(解引用):*指针变量
int num = 1234;
int* p = #
*p <=> num; // *p 等价于 num
指针变量解引用时,具体访问多个少字节数由指针变量的类型决定:
char* p; // *p 访问一个字节
short* p; // *p 访问两个字节
double* p; // *p 访问4个字节
int* p; // *p 访问4字节内存
long long* p; // *p 访问8字节内存
指针变量解引用时可能出现段错误的原因:
1、指针变量中存储的是无效的内存地址(不在maps文件里的地址范围内)。
2、指针变量中存储的是具有只读权限的内存地址,通过指针变量修改内存时也会产生段错误。
const int num = 1234; // num使用的是代码段内存
int main()
{
int* p = (int*)#
*p = 6666; // 强行修改只读权限的内存,会产生段错误
}
3、指针变量中存储的是NULL,解引用时肯定产生段错误。
4、内存块的大小与指针的类型不匹配
int num;
long long* p = (long long*)#
*p = 0xffffffffffffffffull; // 内存越界,可能产生段错误
总结:当指针变量解引用时产生段错误,要在指针变量赋值时改正。
为什么要使用指针:
1、使用指针可以在函数之间共享变量
使用全局变量可以在函数之间共享变量,但使用全局变量容易造成命名冲突,并且在程序运行期间全局变量所使用的data、bss、text内存不会被释放,这多使用全局变量容易造成内存浪费,尽量少使用全局变量,最好不用。
当函数需要返回多个执行结果时,需要在函数之间共享变量,也就是共享变量地址,例如:scanf函数。
2、适当的使用指针可以提高函数的传参效率
c语言的函数传参是值传递(赋值、内存拷贝),比如:double,long double,long long,自定义类型(结构、联合、类),它们的字节数 > 4,如果直接传递变量的值则最少需要拷贝8字节内存数据,而传递变量的地址,只需要拷贝4字节内存数据。
// 以下代码传递变量的地址比直接传递变量的值要节约一半的时间
void func(long double* p)
{
}
int main()
{
long double f = 3.14;
for(int i=0; i<2000000000; i++)
{
func(&f);
f+=1;
}
}
3、使用堆内存必须与指针变量配合
当 int num; 语句时,系统会分配4字节内存(text、data、bss、stack),并让这4字节内存与变量名num建立联系,在之后的代码中使用num就相当于4字节内存,我们把这种功能叫做给内存取名字。
而堆内存无法取名字,当向系统申请一块内存时,系统会返回这块内存的首地址,这块内存无法与变量名建立联系,也就是无法取名字,需要指针变量存储内存的地址以便之后使用这块堆内存,所以说堆内存必须与指针变量配合使用。
练习1:实现一个交换两个整型变量的函数。
#include <stdio.h>
void swap(int* p1,int* p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
/* 此方法只能适用于数值型变量交换
*p1 = *p1 + *p2;