WordPress找不到站点,网站怎么申请微博登录,湖州企业网站建设,wordpress淘宝插件下载地址目录
指针的概念
1. 字符指针
2. 指针数组
3. 数组指针
3.1 数组指针的定义
3.2 数组名VS数组名
3.3 数组指针的使用
4. 数组参数、指针参数
4.1 一维数组传参
4.2 二维数组传参
4.3 一级指针传参
4.4 二级指针传参 5. 函数指针
阅读两段有趣的代码数组名VS数组名
3.3 数组指针的使用
4. 数组参数、指针参数
4.1 一维数组传参
4.2 二维数组传参
4.3 一级指针传参
4.4 二级指针传参 5. 函数指针
阅读两段有趣的代码 6. 函数指针数组计算器的优化 指针的概念 在此之前我们在初阶已经了解过指针 http://t.csdn.cn/KP1CH接下来在本章将带领大伙一起更加深入地学习指针吧 1. 指针就是个变量用来存放地址地址唯一标识一块内存空间。 2. 指针的大小是固定的 4/8 个字节 32 位平台 /64 位平台。 3. 指针是有类型指针的类型决定了指针的 - 整数的步长指针解引用操作的时候的权限。 4. 指针的运算。 这个章节我们继续探讨指针的进阶主题。 1. 字符指针 在指针的类型中我们知道有一种指针类型为字符指针 char* ; 一般使用 : 还有一种使用方式如下 代码 const char* pstr hello world. ; int main()
{char ch w;char *pc ch;*pc w;return 0;
}
int main()
{const char* pstr hello world.;//这里是把一个字符串放到pstr指针变量里了吗printf(%s\n, pstr);return 0;
} 在这里特别容易让同学以为是把字符串 hello world放到字符指针 pstr 里了但是 本质是把字符串 hello world. 首字符的地址放到了 pstr 中。 上面代码的意思是把一个常量字符串的首字符 h 的地址存放到指针变量 pstr 中。 那就有可这样的面试题 这里最终输出的是 这里 str3 和 str4 指向的是一个同一个常量字符串。 C/C 会把常量字符串存储到单独的一个内存区域当几个指针。指向同一个字符串的时候他们实际会指向同一块内存。但是用相同的常量字符串去初始化 不同的数组的时候就会开辟出不同的内存块。所以str1 和 str2 不同 str3 和 str相 同。 #include stdio.h
int main()
{char str1[] hello world.;char str2[] hello world.;const char *str3 hello world.;const char *str4 hello world.;if(str1 str2)
printf(str1 and str2 are same\n);else
printf(str1 and str2 are not same\n);if(str3 str4)
printf(str3 and str4 are same\n);else
printf(str3 and str4 are not same\n);return 0;
} 2. 指针数组 什么是指针数组指针数组是一个存放指针的数组。 这里我们再复习一下下面指针数组是什么意思 int* arr1[10]; //整形指针的数组
char *arr2[4]; //一级字符指针的数组
char **arr3[5];//二级字符指针的数组 3. 数组指针
3.1 数组指针的定义 数组指针是指针还是数组 答案是指针。 我们已经熟悉 整形指针 int * pint ; 能够指向整形数据的指针。 浮点型指针 float * pf ; 能够指向浮点型数据的指针。 那数组指针应该是能够指向数组的指针。 下面代码哪个是数组指针 int *p1[10];
int (*p2)[10];
//p1, p2分别是什么 解释 int ( * p )[ 10 ]; // 解释 p 先和 * 结合说明 p 是一个指针变量然后指着指向的是一个大小为 10 个整型的数组。所以 p 是一个 指针指向一个数组叫数组指针。 // 这里要注意 [] 的优先级要高于 * 号的所以必须加上来保证 p 先和 * 结合。 3.2 数组名VS数组名 对于下面的数组 int arr[10]; arr 和 arr 分别是啥 我们知道 arr 是数组名数组名表示数组首元素的地址。 那arr 数组名到底是啥 //数组名绝大部分情况下是数组首元素的地址但是有两个例外 1.sizeof(数组名) - sizeof内部单独放一个数组名的时候数组名表示整个数组计算得到的是数组的大小。 2.arr - 这里的数组名表示整个数组取出的是地址从地址值的角度来讲和数组首元素的地址是一样的但是意义不一样。 我们看一段代码 #include stdio.h
int main()
{int arr[10] {0};printf(%p\n, arr);printf(%p\n, arr);return 0;
} 运行结果 可见数组名和 数组名打印的地址是一样的。 难道两个是一样的吗 我们再看一段代码 #include stdio.h
int main()
{
int arr[10] { 0 };
printf(arr %p\n, arr);
printf(arr %p\n, arr);
printf(arr1 %p\n, arr1);
printf(arr1 %p\n, arr1);
return 0;
} 根据上面的代码我们发现其实 arr 和 arr 虽然值是一样的但是意义应该不一样的。 实际上 arr 表示的是 数组的地址 而不是数组首元素的地址。细细体会一下 本例中 arr 的类型是 int(*)[10] 是一种数组指针类型 数组的地址 1 跳过整个数组的大小所以 arr1 相对于 arr 的差值是 40. 判断 3.3 数组指针的使用
那数组指针是怎么使用的呢
既然数组指针指向的是数组那数组指针中存放的应该是数组的地址。 看代码 #include stdio.h
int main()
{int arr[10] {1,2,3,4,5,6,7,8,9,0};int (*p)[10] arr;//把数组arr的地址赋值给数组指针变量p//但是我们一般很少这样写代码return 0;
} #include stdio.h
void print_arr1(int arr[3][5], int row, int col)
{int i 0;for(i0; irow; i){for(int j0; jcol; j){printf(%d , arr[i][j]);}printf(\n);}
}
void print_arr2(int (*arr)[5], int row, int col)
{int i 0;for(int i0; irow; i){for(j0; jcol; j){printf(%d , arr[i][j]);}printf(\n);}
}
int main()
{int arr[3][5] {1,2,3,4,5,6,7,8,9,10};print_arr1(arr, 3, 5);//数组名arr表示首元素的地址//但是二维数组的首元素是二维数组的第一行//所以这里传递的arr其实相当于第一行的地址是一维数组的地址//可以数组指针来接收print_arr2(arr, 3, 5);return 0;
} 两个函数的运行结果 拓展
数组访问——用下标的形式打印
int main()
{int arr[10] { 1,2,3,4,5,6,7,8,9,10 };int i 0;int sz sizeof(arr) / sizeof(arr[0]);//下标的形式的印数组for (i 0;i sz;i){printf(%d , arr[i]);}return 0;
}
数组访问——使用指针访问
int main()
{int arr[10] { 1,2,3,4,5,6,7,8,9,10 };int i 0;int sz sizeof(arr) / sizeof(arr[0]);//使用指针来访问int* p arr;for (i 0;i sz;i){printf(%d ,*(p i)); printf(%d , ((*p) i));}return 0;
} 数组访问——数组指针
int main()
{int arr[10] { 1,2,3,4,5,6,7,8,9,10 };int i 0;int sz sizeof(arr) / sizeof(arr[0]);int(*p)[10] arr;for (i 0;i sz;i){printf(%d , *((*p) i));}return 0;
}
4. 数组参数、指针参数 在写代码的时候难免要把【数组】或者【指针】传给函数那函数的参数该如何设计呢 4.1 一维数组传参 一级指针传参 一级指针传参
//void print(int* p, int sz)
//{
// int i 0;
// for (i 0; i sz; i)
// {
// printf(%d\n, *(p i));
// }
//}
//int main()
//{
// int arr[10] { 1,2,3,4,5,6,7,8,9 };
// int* p arr;
// int sz sizeof(arr) / sizeof(arr[0]);
// //一级指针p传给函数
// print(p, sz);
// return 0;
//
//} #include stdio.h
void test(int arr[])//ok?
{}
void test(int arr[10])//ok?
{}
void test(int *arr)//ok?
{}
void test2(int *arr[20])//ok?
{}
void test2(int **arr)//ok?
{}
int main()
{
int arr[10] {0};
int *arr2[20] {0};
test(arr);
test2(arr2);
} 4.2 二维数组传参 这里的*(*(arr i) j))也可换成arr[i][j];
void test(int arr[3][5])//okyes
{}
void test(int arr[][])//okno
{}
void test(int arr[][5])//okyes
{}
//总结二维数组传参函数形参的设计只能省略第一个[]的数字。
//因为对一个二维数组可以不知道有多少行但是必须知道一行多少元素。
//这样才方便运算。
void test(int *arr)//okno
{}
void test(int* arr[5])//okno
{}
void test(int (*arr)[5])//okyes
{}
void test(int **arr)//okno 传过去的是一行指针的地址怎么能用二级指针来接收呢
{}
int main()
{int arr[3][5] {0};test(arr);
}
4.3 一级指针传参 #include stdio.h
void print(int *p, int sz)
{int i 0;for(i0; isz; i){printf(%d\n, *(pi));}
}
int main()
{int arr[10] {1,2,3,4,5,6,7,8,9};int *p arr;int sz sizeof(arr)/sizeof(arr[0]);//一级指针p传给函数print(p, sz);return 0;
} 思考 当一个函数的参数部分为一级指针的时候函数能接收什么参数 比如 void test1(int *p)
{}
//test1函数能接收什么参数
void test2(char* p)
{}
//test2函数能接收什么参数 4.4 二级指针传参 #include stdio.h
void test(int** ptr)
{printf(num %d\n, **ptr);
}
int main()
{int n 10;int*p n;int **pp p;test(pp);test(p);return 0;
} 思考 当函数的参数为二级指针的时候可以接收什么参数 void test(char **p)
{}
int main()
{char c b;char*pc c;char**ppc pc;char* arr[10];test(pc);test(ppc);test(arr);//Ok?return 0;
} 5. 函数指针 首先看一段代码 #include stdio.h
void test()
{printf(hehe\n);
}
int main()
{printf(%p\n, test);printf(%p\n, test);return 0;
} 输出的是两个地址这两个地址是 test 函数的地址。 那我们的函数的地址要想保存起来怎么保存 下面我们看代码 首先能给存储地址就要求 pfun1 或者 pfun2 是指针那哪个是指针 void test()
{
printf(hehe\n);
}
//下面pfun1和pfun2哪个有能力存放test函数的地址
void (*pfun1)();
void *pfun2(); 答案是 pfun1 可以存放。 pfun1 先和 * 结合说明 pfun1 是指针指针指向的是一个函数指向的函数无参数返回值类型为void 。 阅读两段有趣的代码 //代码1
(*(void (*)())0)();
//代码2
void (*signal(int , void(*)(int)))(int); 注 : 推荐《 C 陷阱和缺陷》 这本书中提及这两个代码。 代码 2 太复杂如何简化 typedef void(*pfun_t)(int);
pfun_t signal(int, pfun_t); 6. 函数指针数组计算器改良 数组是一个存放相同类型数据的存储空间那我们已经学习了指针数组 比如 int *arr[10];
//数组的每个元素是int* 那要把函数的地址存到一个数组中那这个数组就叫函数指针数组那函数指针的数组如何定义呢 int (*parr1[10])();
int *parr2[10]();
int (*)() parr3[10]; 答案是 parr1 parr1 先和 [] 结合说明 parr1 是数组数组的内容是什么呢 是 int (*)() 类型的函数指针。 函数指针数组的用途 转移表 例子计算器 #include stdio.h
int add(int a, int b)
{return a b;
}
int sub(int a, int b)
{return a - b;
}
int mul(int a, int b)
{return a * b;
}
int div(int a, int b)
{return a / b;
}
int main()
{int x, y;int input 1;int ret 0;do{printf(*************************\n);printf( 1:add 2:sub \n);printf( 3:mul 4:div \n);printf(*************************\n);printf(请选择);scanf(%d, input);switch (input){case 1:printf(输入操作数);scanf(%d %d, x, y);ret add(x, y);printf(ret %d\n, ret);break;case 2:printf(输入操作数);scanf(%d %d, x, y);ret sub(x, y);printf(ret %d\n, ret);break;case 3:printf(输入操作数);scanf(%d %d, x, y);ret mul(x, y);printf(ret %d\n, ret);break;case 4:printf(输入操作数);scanf(%d %d, x, y);ret div(x, y);printf(ret %d\n, ret);break;case 0:printf(退出程序\n);break;default:printf(选择错误\n);break;}} while (input);return 0;
} 使用函数指针数组的实现 #include stdio.h
int add(int a, int b)
{return a b;
}
int sub(int a, int b)
{return a - b;
}
int mul(int a, int b)
{return a * b;
}
int div(int a, int b)
{return a / b;
}
int main()
{int x, y;int input 1;int ret 0;int(*p[5])(int x, int y) { 0, add, sub, mul, div }; //转移表while (input){printf(*************************\n);printf( 1:add*************2:sub\n);printf( 3:mul*************4:div\n);printf(*************************\n);printf(请选择);scanf(%d, input);if ((input 4 input 1)){printf(输入操作数);scanf(%d %d, x, y);ret (*p[input])(x, y);}elseprintf(输入有误\n);}return 0;
} THE END 这是今日份关于指针的一些分享希望可以帮助到大家如果有什么不足的地方也请家人们给小叶一些好的建议我会不断优化文章的那就让我们一起加油吧哈哈哈哈哈