C语言指针基础
什么是指针
指针就是一个地址,那么如何获取地址?用的是&:即取地址符
- 指针是一个整数
- 获取指针: *
指针变量
- 用来存放地址,也就是存放一个特定的整数(这个的整数可以表示地址)
- 如何产生一个指针变量
- 类型* 变量名;
- 指针变量的两个重要概念
- 指针的类型: 去掉变量名
- 指针所指向的类型:去掉变量名和*号
- 用指针的时候需要保持上述两个类型的一致
int* p;
//类型: int*
//所指向的类型: int --->本质就是指针所操作数据类型
- 不同类型的指针变量
- 所有类型指针占用的字节数都是相同 32位系统下都是4个字节
- 特殊的指针类型: void* (可以转化为任意类型)
- 专门用来初始化指针变量的东西:NULL
- NULL 即 (void*)0
- 防止悬浮指针
- 防止野指针
- 指针变量获取当前地址中的值: *指针变量
指针的运算
- *指针变量: 指针变量所指向的内存存储的值
- p+n或者p-n操作:实质是内存字节偏移,和指向内存存储的数据类型有关
- 求偏移量:p+sizeof(指针所指向的类型)*n
- 对于一个指针变量来说,不会单独的去偏移,一般要指向一段内存做偏移(例如对数组做偏移)
- p++ 和p-- 也算p+n
- 对于不同类型的指针之间是没有什么算术运算的
内存的四区
#include <stdio.h>
void print()
{
static int num = 1; //放入全局区的静态变量,这个代码运行的时候只执行一次
//不做初始化默认为0
num++;
printf("%d\n", num);
}
int main()
{
print(); //num=2;
print(); //num=3;
return 0;
}
关于指针容易出错的地方
#include<stdio.h>
int main()
{
//NULL 即 (void*)0
int* p = NULL; //0存放在常量区
//*p = 1234; //不能修改0所在的内存 会出现写入访问权限冲突
//printf("%d", *p);
#include<stdio.h>
int main()
{
char* str = "ILoveyou"; //解析: 把这段内存的首地址赋值给指针变量str
char* pchar;
puts(str);
pchar = "ILoveyou";
//*pchar = 'M'; //写入访问权限冲突。
//字符串位于常量区,不能被修改
puts(pchar);
return 0;
}
#include<stdio.h>
int main()
{
//数组位于栈区
char array[10] = "ILoveyou";//将字符串放入数组中
pchar = &array[0];
*pchar = 'M';//位于栈区的数据可以被改变
puts(array);
}
#include <stdio.h>
char* returnPoint()
{
//函数调用完,内存会被系统回收(清除所有数据)
//所以不允许返回局部变量地址
char array[10] = "ILoveyou";
//%s 打印方式:从首地址开始,打印到\0
char* p = &array[0];
return p;
//解决方法:把数据存到栈区,返回堆区这段内存的首地址
}
int main()
{
int* result = returnPoint();
puts(result);
puts(result);
puts(result);
puts(result);
//因为函数被调用完后,数据会被回收,所以就读取不到指针所指向的地址中的数据
return 0;
}
万能指针
- 什么是万能指针
- 万能指针就是void* 类型的指针变量
- 万能指针在访问数据的时候必须做强制类型类型
- 万能指针应用: 统一接口(统一函数传参)
#include <stdio.h>
int main()
{
int num = 10;
void* pVoid = # //解析方式: pVoid=# 不是*pVoid=#
printf("%d\n", *(int*)pVoid);
double dNum = 1.11;
pVoid = &dNum;
printf("%.3lf\n", *(double*)pVoid);
//万能指针使用的时候要强制转换为目标类型(就指向数据类型的指针)
return 0;
}