二级指针和多级指针
1.指针使用的注意事项
1.1 在运算的过程中,不断地改变指针的位置,
void main(){
char* name = "Darren"; // 原name值不变。
char* tempName = name; // 临时缓存指针
for(int i=0; i<6; i++){
printf("%c ", *tempName);
tempName++; // 指针偏移了
}
// 后面还要操作name,如打印name。就打印不了啦。所以要保存头指针。
}
1.2 给一个字符串赋值
强调一个概念:指针变量与 指针 所指向的内存变量 是两个不同的概念。
指针变量不断赋值,改变的是指针的指向。
void set(char** str) { // 传的不是空地址,而是name的地址。
*str = "Darren"; // str地址指向啥?指向的是name的地址
// 指针变量不断赋值,改变的是指针的指向。
}
void main() {
char *name = NULL; // 0x0000000
set(&name); // 最终指向静态常量区的 "Darren", 所以这边不会报NULL空指针问题。传入name变量的地址。
printf("name=%s", name);
name = "Jack"; // 最终指向静态常量区的 "Jack"
getchar();
}
2. const 关键字
在C和C++里面,会有区别。
常量变量:变量不能修改。但是可以通过指针修改里面的值。
常量指针:
指针常量:
void main() {
// 常量变量
const int number = 100;
// 常量指针(被常量指针修饰的,是不能被修改的,但是可以修改它的地址)
cosnt int* numberP = &number;
// *numberP = 200;
int number2 = 900;
numberP = &number2;
// 指针常量(指针常量的指针,是不能被修改的)
int* const numberP2 = &number;
*numberP2 = 300;
numberP2 = & number2;
const int* const numberP3 = &number;
// 值不能改,且指针也不能修改。
// 在C里面,是一个忽悠类型(假命题),
int* numberP0 = &number;
*numberP0 = 300;
printf("number=%d\n", number); // 300
}
3.二级指针的内存模式
3.1 指针数组
指针数组:数组指针指向的是数组元素的首地址。
二级指针,又可以看成二维数组. 指针数组 和 二级指针 是同一个概念。两种定义方式都可。
struct FILE {
char* fileName;
int length;
};
void main() {
char* name = "Darren";
char** nameP = &name; // 二级指针,又可以看成二维数组
// eg:压缩文件,指定两个FILE,一个输入一个是输出。
// 定义一个FILE* 指针数组,方式1
FILE* file[2] = {{"in.mp4"}, {out.mp4}};
FILE** file2 = file; // 定义方式2,指针数组,也可以看成二级指针。其实和上面是同一个概念。
// 数组指针指向的是数组元素的首地址。
int number =100;
int* numberP = &number; // 一级指针,可以看成一维数组
}
3.2 字符二维数组
char** namep; // char * * namep;指针数组
// 打印方法。
void print(char** strs, int len) {
for(int i=0;i<len;i ++) {
// printf("%s\n", strs[i]); // [] 相当与下面的挪动指针。
printf("%s\n", *(strs[i] + i));
}
}
void print2(char strs[10][30], int len) { // 涉及二级指针做参数传递的问题。
for(int i=0; i<len;i ++) {
// printf("%s\n", strs[i]); // [] 相当与下面的挪动指针。
printf("%s\n", *(strs[i] + i));
}
}
void main() {
// 第1种定义方式:
//char* name[10] = {"Darren","Jack","Rose"}; // 后面7个指向空地址。这几个数据在静态常量区。
// 打印的时候出错,赋值也出错。
// char** name1 = {"Darren"}; // char* = Darren 这种方式定义不行。也不能定义是批量赋值多个。
// 直接去赋值,C和C++编译器,会把他当成二级指针,而不是指针数组。
//print(name, 10);
// 第2种定义方式:10个字符串,每个字符串占用30字节。
char name[10][30] = {"Darren","Jack","Rose"}; // 这几个数据,都是从静态常量区coy到栈buff里面的。
// print(char** strs, int len) 读取出错。
// 指针++的步长,不一样。要指定步长30。
print2(name, 3);
// 第3种定义方式-【最常用】:malloc 动态开辟内存,在堆内存上申请。
int number = 3;
char** params = malloc(sizeof(char*) * number); // 开辟二维数组,里面存放指针char*
// 开辟一维数组
for(int i=0; i<number; i++){
params[i] = malloc(sizeof(char) *100); // 开辟三块内存,每块可以存100字节数据,然后给指针首地址赋值。
sprintf(params[i], "i = %d", i); // 赋值内容:i=1
}
print(params, number);
// 释放,先释放一维数组。
for(int i=0; i<number; i++){
if(params[i]!=NULL){
free(params[i]);
params[i] = NULL;
}
}
if(params!=NULL) {// 再释放二维数组(也可以看做一维数组,只不过这个一维数组里面,存放的元素是一级数组指针char*)
free(params);
params = NULL;
}
getchar();
}
4. 多级指针,给二维数组赋值。
- 多级指针的用法,使用的一些场景.赋值。
想把字符串数组初始化(开辟内存),写到另一个方法里面。
void initParams(char*** params, int nubmer) { // 三级指针char*** params。用的最多的就是二级指针(数组指针)
char** tempParams = malloc(sizeof(char*) * number); // 开辟二维数组,里面存放指针char*
// 开辟一维数组
for(int i=0; i<number; i++){
tempParams[i] = malloc(sizeof(char) *50); // 开辟三块内存,每块可以存50字节数据,然后给指针首地址赋值。
sprintf(params[i], "i = %d", i); // 赋值内容:i=1
}
*params = tempParams; //地址赋值
}
void main() {
char** params = NULL; // 想把字符串数组初始化(开辟内存),写到另一个方法里面。
int number = 4;
initParams(¶ms, number); // 要传地址,不能直接传params
print(params, number);
// 释放。free()
}
网友评论