c/c++:数组做函数参数,传入函数的首地址,相当于传址,指针做函数返回值,数组禁止做c语言中函数的返回值
2022找工作是学历、能力和运气的超强结合体,遇到寒冬,大厂不招人,此时学会c++的话,
我所知道的周边的会c++的同学,可手握10多个offer,随心所欲,而找啥算法岗的,基本gg
提示:系列c++学习的基础和高阶知识,用于公司生产实践中,实实在在的公司部署产品要用的,因为c++速度快,
而java和Python速度慢,自然往硬件里面部署算法啥的,都得用c++或者c,因此本科学的c很重要,后来的Python或者java就没有那么重要了,
c/c++系列文章:
【1】c++:c语言优缺点,visual studio2019如何新建项目,写hello world程序
【2】c/c++:gcc安装,gcc编译hello world文件,system函数调用系统命令,sleep函数
【3】linux下gcc的编译过程和功能,预处理,编译,汇编,链接,.c预处理为.i文件.s文件.o文件.exe文件
【4】c/c++:windows平台下依赖的动态库,c底层是汇编语言,程序断点调试,反汇编,vs快捷键
【5】c/c++:数据类型,常量变量,标识符,有符号整型,无符号unsigned,字符类型,字符串类型,实数类型,浮点型,科学计数法
【6】c/c++:2进制、8进制、10进制、16进制和进制之间的转换,c语言输出匹配格式%
【7】c/c++:原码,反码,补码和常见的数据类型取值范围,溢出
【8】c/c++:类型限定符,printf输出格式,putchar,scanf,getchar
【9】c/c++:算术运算符,赋值运算,逻辑运算,比较运算,三目运算,逗号运算,数据类型转换
【10】c/c++:顺序结构,if else分支语句,do while循环语句,switch case break语句
【11】c/c++:for循环语句,分号不可省略,表达式可以省略,猜数字游戏,跳转语句continue,break,避免写goto
【12】c/c++:一维数组,初始化数组,循环打印数组,计算数组存储空间,数组元素个数,数组逆序算法
【13】c/c++:二维数组,数组的行数和列数求法sizeof,数组初始化不同形式,5个学生,3门功课,求学生总成绩和功课总成绩
【14】c/c++:visual studio的代码快捷键,VS设置自定义默认代码,使用快捷键
【15】c/c++:三维数组,字符数组和字符串,统计字符串中字符出现的频次,scanf输入空格,正则匹配表达式
【16】c/c++:gets(),fgets(),puts(),fputs(),strlen(),字符串拼接函数
【17】c/c++:函数的作用,分类,随机数,函数定义,调用,申明,exit()函数,多文件编程,防止头文件重复
【18】c/c++:指针,指针定义和使用,指针大小4字节,野指针,空指针*p=NULL
【19】c/c++:万能指针,泛型指针,const int *p,int const *p,int *const p,const int *const p,指针与数组,p++,
【20】c/c++:指针p+p-p*p/,数组&a+1,指针减指针,指针实现strlen函数,指针的比较运算,指针数组,多级指针
【21】c/c++:栈帧,传值,传址,实参传值给形参,传地址指针给形参
c/c++:指针做函数参数,传递有效地址值,非野指针
这个上一节我们说过了
简单
就是传地址而已
数组做函数参数,很重要的知识点
冒泡排序那个事情
咱们来说一把
咱们直接传递数组看看?
本来数组就是一个指针地址,所以传进去之后,它针对数组本身实参直接排序了
确实是这样的
void printArr3(int arr[], int n);//申明
void bubble_sort2(int arr[], int n)
{
if (sizeof(arr) == 0) return;
//冒泡排序
//int n = sizeof(arr) / sizeof(arr[0]);
for (int i = n - 1; i >= 0; i--)
{
for (int j = i; j < n - 1; j++)//每次都是右边i--n-1对比一把,大的冒泡
{
if (arr[j] > arr[j + 1]) swap2(arr, j, j + 1);//交换
}//知道i=0,整体比一遍
}
printf("函数内部");
printArr3(arr, n);
}
void printArr3(int arr[], int n)
{
//整体打印一个数组
if (sizeof(arr) == 0) return;
//冒泡排序
//int n = sizeof(arr) / sizeof(arr[0]);
for (size_t i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
void f78(void)
{
int arr[] = { 4,1,3,2 };
int n = sizeof(arr) / sizeof(arr[0]);
printArr3(arr, n);
bubble_sort2(arr, n);//直接传入数组
printArr3(arr, n);
}
int main(void)
{
f78();
system("pause");
return 0;
}
这跟java和c++一模一样
因为他们都是建立在c之上的
但是注意,你能否在数组内部求其长度???
不能
我之前就炸锅
void bubble_sort2(int arr[], int n)
{
if (sizeof(arr) == 0) return;
//冒泡排序
int k = sizeof(arr) / sizeof(arr[0]);
printf("%d\n", k);//看看n
for (int i = n - 1; i >= 0; i--)
{
for (int j = i; j < n - 1; j++)//每次都是右边i--n-1对比一把,大的冒泡
{
if (arr[j] > arr[j + 1]) swap2(arr, j, j + 1);//交换
}//知道i=0,整体比一遍
}
printf("函数内部");
printArr3(arr, n);
}
为啥呢,因为冒泡排序函数,它是一个栈帧,与main不同
里面申请了一个数组变量
但是数组本质就是一个指针,指针只放一个地址
所以就是4字节的地址,仅此而已
你求arr的size就是4字节
求arr[0]的size也就4字节
仅此而已
故k=1
void bubble_sort2(int arr[], int n)
{
if (sizeof(arr) == 0) return;
//冒泡排序
int k = sizeof(arr) / sizeof(arr[0]);
printf("%d\n", k);//看看n
printf("%p\n", &arr);//看看n
printf("%p\n", &arr[0]);//看看n
printf("%d\n", *arr);//看看n
printf("%d\n", arr[0]);//看看n
for (int i = n - 1; i >= 0; i--)
{
for (int j = i; j < n - 1; j++)//每次都是右边i--n-1对比一把,大的冒泡
{
if (arr[j] > arr[j + 1]) swap2(arr, j, j + 1);//交换
}//知道i=0,整体比一遍
}
printf("函数内部");
printArr3(arr, n);
}
冒泡函数中arr的地址,是冒泡函数的栈帧中的临时空间,它里面存的是main函数的arr[0]的地址
arr[0]的地址,是main函数的栈帧中的临时空间
也就是说,函数做形参,实际上是传入了地址,地址即指针
void bubble_sort3(int* arr, int n)
{
if (sizeof(arr) == 0) return;
//冒泡排序
int k = sizeof(arr) / sizeof(arr[0]);
printf("%d\n", k);//看看n
printf("%p\n", &arr);//看看n
printf("%p\n", &arr[0]);//看看n
printf("%p\n", arr);//看看n
printf("%d\n", arr[0]);//看看n
for (int i = n - 1; i >= 0; i--)
{
for (int j = i; j < n - 1; j++)//每次都是右边i--n-1对比一把,大的冒泡
{
if (arr[j] > arr[j + 1]) swap2(arr, j, j + 1);//交换
}//知道i=0,整体比一遍
}
printf("函数内部");
printArr3(arr, n);
}
所以
下面俩都等价的
void bubble_sort3(int* arr, int n)==void bubble_sort3(int arr[], int n)
懂了吗
数组做形参,相当于指针做形参
屌爆了
我们来看看它们的栈帧的分配过程
所以要把函数真的长度,重新搞一个参数放进去,我为啥要定义其长度n知道了吧
后来java改了这个骚操作,因为太麻烦了。
当年大一压根没有学会这些东西
稀里糊涂
时隔这多年,为了工作所需,又重新学一遍c,真的美滋滋
a[i]=*(a+i)
所以只要首地址进去就行,
自然访问数组就很方便了
指针做函数的返回值
int* f()
返回一个地址,估计很数组有挂钩
int m = 100;//全局变量
int* xingf(int a, int b)
{
return &m;//地址呗
//结束返回指针
}
void f79(void)
{
int* p=NULL;
p = xingf(10, 20);//返回p
printf("全局变量m的地址%p\n", &m);//本身
printf("返回来指针的地址:%p\n", p);//本身
printf("%d\n", *p);//里面存的东西
}
int main(void)
{
f79();
system("pause");
return 0;
}
全局变量是整个程序结束之后才会gg的
m地址,是你f返回的指针
对不对
解引用就是100
所以指针作为函数的返回值,好说
只要是返回地址,咱们解引用操作的就是地址
int m = 100;//全局变量
int* xingf(int a, int b)
{
int n = 1234;
return &n;//地址呗
//结束返回指针
}
void f79(void)
{
int* p=NULL;
p = xingf(10, 20);//返回p
printf("全局变量m的地址%p\n", &m);//本身
printf("返回来指针的地址:%p\n", p);//本身
printf("%d\n", *p);//里面存的东西
}
int main(void)
{
f79();
system("pause");
return 0;
}
要注意哦
你局部斌量,在调用完后,栈帧就会gg
你的&n压根就是野指针,没意义
返回一个随机地址
得到的数27不再是1234
这点要清楚?
所以说,指针作为返回值,不能返回函数内部的局部变量的地址值,懂吧?
数组做函数的返回值,简单
禁止!!!
你只能写指针做返回值
数组本身就是指针
哈哈哈哈
懂?
总结
提示:重要经验:
1)
2)学好c++,即使经济寒冬,手握10个大厂offer绝对不是问题!
3)笔试求AC,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。