IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【c语言——指针的进阶(上)】 -> 正文阅读

[C++知识库]【c语言——指针的进阶(上)】

? hellow 大家好久不见了,最近一直在忙着期末考试,博客也好久没写了,这几天花了一些时间把鹏哥c语言指针的进阶看完,我就打算用两篇文章浅浅的总结一下指针进阶中我们要学的一些基础知识,也希望大家能指出文章中的不足。


目录

1 字符指针

?2 指针数组 and 数组指针

?3 数组参数 and 指针参数

?3.1 一维数组传参

?3.2 二维数组传参

3.3 一级指针传参

3.4 二级指针传参

4 函数指针数组


?

1 字符指针

相信大家对一些基本的字符指针常识已经有所了解,这里便不再多说。那么下面的代码你能够理解吗?

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	const char* pc = "hellow world";//这里是把整个字符串放在pc里了吗?
	return 0;
}

答案显然不是,这里的pc存放的是常量字符串首元素的地址,也就是h的地址。有了这个认识,那我们来看接下来的代码

#include <stdio.h>
int main()
{
 ? ?char str1[] = "hello bit.";
 ? ?char str2[] = "hello bit.";
 ? ?const char *str3 = "hello bit.";
 ? ?const char *str4 = "hello bit.";
 ? ?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; 
}

那么结果究竟是什么呢?

?我们在vs中运行一下:

dae3896389b241aeb805bae17636cab7.png

这里可以明显的看出来str1与str2不相等,str3与str4相等。str1与str2是两个不同的字符数组,尽管它们存放的内容是相同的,但是它们的地址却是不相同的。而"hellow bit"这个常量字符串系统给它开辟空间时只开辟了11个字节大小的空间给它 ,当有两个指针共同指向相同字符串首元素地址时不会额外再给其中一个指针分配内存,所以str3和str4是一回事,这也就很好的解释了为什么前面会有const修饰。


?2 指针数组 and 数组指针

?下面的哪个是指针数组?哪个是数组指针你能够分清吗?

int* p1[10];

int (*p2)[10];

?由于[]的优先级大于*的优先级,所以很容易就能够判断出p1是指针数组,p2是数组指针

那么来点稍微有点难度的,下面的parr1又是什么意思呢?

int (*parr1[10])[5];

?由于[]的优先级大于*,我们可以知道parr1是一个数组,数组里有10个元素,每个元素的类型是int (*)[5] ,也就是一个数组指针,该指针指向的数组有5个元素,每个元素的类型是int.


?3 数组参数 and 指针参数

?3.1 一维数组传参

#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);
}

上面这几种传参方式都是没有问题的,也很容易理解

?3.2 二维数组传参

void test(int arr[3][5])//ok?
{}
void test(int arr[][])//ok? // 不行
{}
void test(int arr[][5])//ok?
{}
//总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。
//因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。
//这样才方便运算。
void test(int *arr)//ok? // 不行
{}
void test(int* arr[5])//ok? // 不行
{}
void test(int (*arr)[5])//ok?
{}
void test(int **arr)//ok? // 不行
{}
int main()
{
int arr[3][5] = {0};
test(arr);
}

3.3 一级指针传参

#include <stdio.h>
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;
}

3.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;

4 函数指针数组

数组是一个存放相同类型数据的存储空间,那我们已经学习了指针数组, 比如:
?
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");
 breark;
 ? ? ? ?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);
 ? ? ? ? }
 ? ? ? ? ?else
 ? ? ? ? ? ? ? printf( "输入有误\n" );
 ? ? ? ? ?printf( "ret = %d\n", ret);
 ? ? }
 ? ? ?return 0; 
}

好啦,指针的进阶(上)我就先分享到这里了,(下)我会在这两天整理出来,也希望大家多多支持!

?

?

?8903802ddfb2402480c0834745f9d46b.jpeg

?

?

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 22:37:15  更:2022-07-04 22:39:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/12 17:28:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码