一.指针变量初始化
指针变量的初始化就是给它赋予一个地址值,让它指向某个内存位置。以下是一些初始化指针的常见方式:
1. 初始化为NULL:
指针可以被初始化为`NULL`,表示它不指向任何有效的内存地址。这是指针的默认状态,也是在没有具体内存地址可以指向时的一个安全选项。
int *p = NULL;
2. 指向一个变量:
指针可以被初始化为指向一个已经声明的变量的地址。
int a= 10;
int *p = &a; // p现在指向a的地址
3. 指向数组的第一个元素:
数组名本身就是一个指向数组第一个元素的指针。你可以将指针初始化为数组的地址。
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr; // p现在指向数组arr的第一个元素
4. 函数返回地址:
函数可以返回一个指针,指向动态分配的内存或者静态分配的内存。
int* createArray(int size) {
int *newArray = malloc(size * sizeof(int)); // 使用malloc分配动态内存
if (newArray) {
// 初始化数组等操作
}
return newArray;
}
int *p = createArray(10); // p现在指向由createArray函数分配的内存
5. 指针数组:
可以创建一个指针数组,每个元素都是一个指针。
int *pArray[10]; // 创建一个包含10个int指针的数组
int var1 = 1, var2 = 2;
pArray[0] = &var1;
pArray[1] = &var2;
6. 初始化为静态或全局变量的地址:
指针也可以指向静态或全局变量。
static int staticVar = 100;
int *p = &staticVar; // p指向静态变量staticVar的地址
7. 使用指针的指针:
可以创建一个指向指针的指针,这在某些情况下很有用,比如实现函数参数的间接引用。
int a = 5;
int *p1 = &a;
int **p2 = &p1; // p2是一个指向指针的指针,它指向p1的地址
二.指针作为函数参数
形参 -- 指针类型 变量 ,用来接收实参 (实参是要操作的内存空间的地址)
实参 -- 要修改谁,就把谁的地址传过去
//要保证 空间有效
注意: 被调函数中 一定要有 *p 运算 //(间接访问的操作)
值传递 //只是 实参数据 赋值了形参
地址(指针)传递 //传的是地址 --可以实现被调修改主调
例如:
1. 实现两个数的求和
结果,通过参数带出来
2.找出两个数最大值(指针):
三. 一维数组的指针
int a[5]; //一维整型数组
//数组名
// 类型 --- 数据类型 int[5]
// 值 --- 数组首元素的地址 --- 常量
//数组名是个常量,不能做自增自减运算
eg:*a++(a是个数组名,是个常量,不能做自增减的运算所以会报错)
1.定义一个什么类型的指针变量?
int *p = a;
int *p = &a[0];
2.谁能代表数组所在空间的首地址?
数组名 -- 数组首元素的地址
这个地址值的类型
a <=> &a[0]
//a[0]的数据类型 -- int型
//&a[0] 地址的类型 -- int *
int *p = a; //表示 p指向数组a
*p <=> a[0]
指针的运算: & *
int *p; //p 的类型 int *
*&p //地址
//int* *
p+1 //加n 表示 跳过了n个基类型
p-1
p++
p--
p - q //表示差了多少元素(基类型)
//必须是同一类型的指针
p + q //不行 +-*/都不行
*(p+i) <=> a[i] <=> *(a+i)
a[i] <=> *(a+i)
i[a] <=> *(i+a)
数组作为函数参数
形参 -- 数组形式 //本质上是一个指针类型变量
int *a
数组长度
int len
实参 -- 数组名
代表数组首地址
例如:求数组最大值
选择排序:
冒泡排序:
插入排序:
二分查找: