我想大多数人学习C语言的时候都曾经接触过冒泡排序,但是今天冒泡排序的实现并不是引起我思考的地方。当我写好冒泡排序的相关代码,准备将它封装成一个函数的时候,那括号里面的参数引起了我深深的思考。
#include <stdio.h>
void maopaos(int arr[],int len) {
int i, j, t;
for (i = 0; i < len - 1; i++) {
for (j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
t = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = t;
}
}
}
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
}
void mainss() {
int arr[] = {-1, 2, -3, 3, 7, 8, 1};
int len = sizeof(arr) / sizeof(int);
maopaos(arr,len);
}
正如这部分关于冒泡排序的代码当我封装成maopaos(int arr[],int len)函数的时候,我总觉的两个参数很麻烦。毕竟当我要用这个函数进行冒泡排序的时候,直接传一个数组参数多好。maopaos(int arr[ ]).就是最理想的,不需要再添加一个关于数组长度的len.然后我就开始改了,比如这样:
#include <stdio.h>
void maopaos(int arr[]) {
int i, j, t;
int len = sizeof(arr) / sizeof(int);
printf("arr数组的长度是:%d\n",len);
for (i = 0; i < len - 1; i++) {
for (j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
t = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = t;
}
}
}
for (i = 0; i < len; i++) {
printf("数组的元素是:%d ", arr[i]);
}
}
void main() {
int arr[] = {-1, 2, -3, 3, 7, 8, 1};
maopaos(arr);
}
但是当我运行的时候,却出现了缺斤少量的情况。
我这么多元素的数组,最后只剩两个,难道被狗吃了?那么为什么呢?
接着我写了一个简单的测试代码探究为什么在函数内不能精确算数组的长度:
#include <stdio.h>
void suzu(int arr[]){
//将传入的数组的长度求出
int len=sizeof (arr)/sizeof (int);
printf("函数内数组长度%d:",len);
}
void main(){
//定义一个测试数组
int a[]={1,2,3,45,67,12};
//求出数组的长度
int length=sizeof (a)/sizeof (int);
//将长度输出
printf("数组长度%d\n",length);
//调用函数
suzu(a);
}
运行结果为:
显然函数内的数组长度是不对的
后来查找了一下关于函数形参的知识:
默认是引用传递的数据类型有:指针和数组
所谓引用传递即是:变量存储的是一个地址,这个地址对应的空间才真正存储数据(值)
那也就意味着suzu(int arr[])里面的arr比不是一个真正意义上的数组,而是一个地址。于是我又开始测试:
#include <stdio.h>
void suzu(int arr[]){
//将传入的数组的长度求出
int len=sizeof (arr)/sizeof (int);
printf("函数内数组长度%d:\n",len);
printf("该函数形参的地址值为%p",arr);
}
void main(){
//定义一个测试数组
int a[]={1,2,3,45,67,12};
//求出数组的长度
int length=sizeof (a)/sizeof (int);
//将长度输出
printf("数组长度%d\n",length);
//调用函数
printf("a数组的地址值是:%p\n",&a);
suzu(a);
}
运行结果为:
这就说明了**suzu(int arr[])**中的arr的确是一个存放地址的变量。
为了进一步论述,我试着通过*arr的操作取到数数组中的元素;
#include <stdio.h>
void suzu(int arr[]){
//将传入的数组的长度求出
int len=sizeof (arr)/sizeof (int);
printf("函数内数组长度%d:\n",len);
printf("该函数形参的地址值为%p\n",arr);
printf("根据地址取值%d ",*arr);
printf("%d ",*(arr+1));
printf("%d ",*(arr+2));
printf("%d ",*(arr+3));
}
void main(){
//定义一个测试数组
int a[]={1,2,3,45,67,12};
//求出数组的长度
int length=sizeof (a)/sizeof (int);
//将长度输出
printf("数组长度%d\n",length);
//调用函数
printf("a数组的地址值是:%p\n",&a);
suzu(a);
}
运行结果为:
看到这里也就解释开头冒泡排序需要同时传入数组和数组长度两个形参的原因了:我们再次回到那段代码;
#include <stdio.h>
void maopaos(int arr[]) {
int i, j, t;
int len = sizeof(arr) / sizeof(int);//求得是形参变量用于存放数组地址的arr的长度。
printf("arr数组的长度是:%d\n",len);
for (i = 0; i < len - 1; i++) {
for (j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
t = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = t;
}
}
}
for (i = 0; i < len; i++) {
printf("数组的元素是:%d ", arr[i]);
}
}
void main() {
int arr[] = {-1, 2, -3, 3, 7, 8, 1};
maopaos(arr);
}
也不难解释在函数maopao(int arr[]) 中arr的长度是2.一个存放地址的变量大小当然是2,。
不过最后还是得掌握函数的传参知识:
1.默认是引用传递的数据类型有:指针和数组
2.所谓引用传递即是:变量存储的是一个地址,这个地址对应的空间才真正存储数据(值)
又加深了一个知识点!