一、初识指针
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdbool.h>int main(void)
{
int * p;
/*
1.p是变量的名字,int*表示p变量存放的是int类型变量的地址,
2.P是变量名字,p的数据类型是int*类型
3.所谓int*类型,实际就是存放int变量地址的类型
*/
int i = 3;
p = &i;
/*
1. p保存了i的地址,因此P指向i
2. P不是i,i也不是P,修改p的值不影响i的值,修改i的值也不会影响P
3. 如果一个指针变量指向某个普通变量,则 *指针变量 就完全等同于 普通变量
例子:
如果P是个指针变量,并且p存放了普通变量i的地址,则p指向了普通变量i
*p 就完全等同于 i
*/
//p = i; //错误,因为p只能存放int类型变量的地址
return 0;
}
二 、指针
1.指针定义
指针就是地址,而地址是内存单元的编号(从0开始的非负整数,编号范围:4G),每个内存 单元的大小是1个字节
指针本质就是一个操作受限的非负整数。
2.指针与指针变量区别
指针就是地址,地址就是指针,地址就是内存单元的编号
指针变量-是存放地址的变量
注意:通常口头把指针变量简称指针,实际它们含义并不一样
3.指针的重要性
- 表示一些复杂的数据结构
- 快速的传递数据
- 使函数返回一个以上的值
- 能直接访问硬件
- 能够方便的处理字符串
- 是理解面向对象语言中引用的基础
4.指针的分类
- 基本类型指针
* 的含义
1>定义指针变量
int *p 定义了一个名字叫p的变量,int *表示p只能存放int类型变量的地址
2.>指针运算符
如果p是一个指针变量,则*p 表示 以p的内容为地址的变量
- 指针和数组
1> 指针和一维数组的关系
一维数组名------是指针常量,它存放的是一维数组第一个元素的地址
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main(void)
{
int a[5]; //a是数组名,5是数组元素个数,元素就是变量
//int a[3][4];
int b[3];
a=&a[2] //错误,因为a是一个指针常量
printf("%#X\n", &a[0]); //结果 0XA5D6F7B8
printf("%#X\n", a); //0XA5D6F7B8
// 一维数组名------是指针常量,它存放的是一维数组第一个元素的地址
return 0;
}
2> 下标和指针的关系
如果p是指针变量,则 p[i] 永远等价于 *(p+i),
*(p+i) 表示的是 地址是(p+i)所指向的元素
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void f(int* arr, int len)
{
arr[3] = 88; //arr[3] 等价于 *(arr+3)
}
int main(void)
{
int a[6] = { 1,2,3,4,5 ,6};
printf("%d\n", a[3]); //结果 是 4
f(a, 6); //a是数组名称,存放的是第一个元素的地址,类型是int*
printf("%d\n", a[3]); //结果是 88
return 0;
}
3>确定一个一维数组需要的参数
数组第一个元素地址 + 数组的长度
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void f(int * arr,int len)
{
int i;
for (i = 0; i < len; i++)
{
printf("%d ", arr[i]); //arr[i]等价于*(arr+i),也等价于a[i],也等价于*(a+i)
}
}
int main(void)
{
int a[5] = { 1,2,3,4,5 };
f(a,5); //a是数组名称,存放的是第一个元素的地址,类型是int*
return 0;
}
4>指针变量的运算
指针变量不能相加,不能相乘除
如果两个指针变量指向的是同一块连续空间中的不同存储单元,则这两个指针变量才 可以相减
# define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
int i = 5;
int j = 10;
int* p = &i;
int* q = &j;
//p-q没有实际意义
int a[5];
p = &a[1];
q = &a[4];
printf("p和q所指向的单元相隔%d个单元\n", q - p);
//结果:p和q所指向的单元相隔3个单元
return 0;
}
5> 一个指针变量 占多少字节?
sizeof(数据类型) -----返回值是该数据类型所占的字节数
例子:sizeof(int)=4 sizeof(char) =1 sizeof(double)=8
sizeof(变量名)----返回值是该变量所占的字节数
# define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
char ch = 'a';
int i = 99;
double x = 9.9;
char* p = &ch;
int* q = &i;
double* r = &x;
printf("%d %d %d\n", sizeof(p), sizeof(q), sizeof(r)); //在64位下,结果是 8,8,8
return 0;
}
总结:
- 一个指针变量,无论它指向的变量占几个字节,该变量本身只占4个字节(32位平台)
(指针的大小在32位平台是4个字节,在64位平台是8个字节)
- 一个变量的地址是使用该变量首字节的地址来表示的
三、指针类型
![](https://img-blog.csdnimg.cn/direct/070819457bfa4968bc7c0ae3506deb34.png)
![](https://img-blog.csdnimg.cn/direct/a76f8c8cf7a44e6ca3c7ec73d76c5421.png)
![](https://img-blog.csdnimg.cn/direct/db94268b64844873b862d50c42a16d91.png)
四 指针运算
1.指针-指针
指针-指针的绝对值,表示2个指针之间元素的个数
备注:指针减去指针的前提是,指向同一块空间的2个指针才能相减
# define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
//方法一
int my_strlen1(char* str)
{
int count = 0;
while (*str !='\0')
{
count++;
str++;
}
return count;
}
//方法二 指针-指针
int my_strlen2(char* str)
{
char* start = str;
while (*str != '\0')
{
str++;
}
return str-start;
}
int main()
{
int len = my_strlen1("abcdef");
printf("%d\n", len);
int len2 = my_strlen2("abcdef");
printf("%d\n", len2);
return 0;
}
五 指针与数组
# define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
int arr[10] = { 0 };
int* p = arr;
int sz = sizeof(arr) / sizeof(arr[0]);
int i;
for (i = 0; i < sz; i++)
{
printf("%p------%p\n", &arr[i], p + i);
}
for (i = 0; i < sz; i++)
{
//printf("%d ", arr[i]);
//printf("%d ", *(p+i));
printf("%d ", *(arr+i));
}
return 0;
}
六 、野指针
概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
# define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
int* p;
//P没有初始化,就意味着没有明确的指向
//一个局部变量不初始化,放的就是随机值
*p = 10; //非法访问内存,p就是野指针
return 0;
}