推广 热搜: 广场  Java  Word  app  营业  微信公众号  北京代理记账  商城  代理记账  商标交易 

c语言中怎么交换指针数组里的值 c语言一维数组如何冒泡排序?

   2023-04-28 企业服务招财猫60
核心提示:c语言一维数组如何冒泡排序?冒泡排序是一种常见的排序方法,反复访问要排序的元素,依次比较相邻的两个元素,如果前面大于后面就交换。用C语言实现冒泡排序时,需要使用两个循环。对于n个元素的数组A,外循环I

c语言一维数组如何冒泡排序?

冒泡排序是一种常见的排序方法,反复访问要排序的元素,依次比较相邻的两个元素,如果前面大于后面就交换。用C语言实现冒泡排序时,需要使用两个循环。对于n个元素的数组A,外循环I的取值范围为0到n-1,内循环J的取值范围为0到n-1-i,若A[j]GTA[j1],则两个元素互换,直到循环结束,此时C语言中一维数组的冒泡排序完成。希望以上回答能帮到你。

c语言可以泛型编程吗?如何实现?

泛型编程是一种非常常见的编程方法。主要目的是实现静态绑定,使函数可以接受不同类型的参数,并在编译时确定正确的类型。

许多语言都支持泛型编程。例如,在C中,可以使用函数模板和类模板来实现泛型编程。在单一继承的语言中,如Java、Objective-C或C#,也可以使用similar和NSObject类型进行编程。在具有类型推理功能的编程语言(如Swift)中,可以直接使用泛型编程。

但C语言是高级语言编程的基础语言,如何用C语言实现泛型编程确实是个问题。首先,C语言不支持函数重载和模板类型,实现起来真的很难。

0x01通用指针简介(void*)

Void*是C语言中的一种类型。众所周知,在大多数编程语言中,void类型表示所谓的空类型,比如一个函数返回一个空类型void,这是非常常见的用法。

注意:void的返回值并不意味着没有返回值,而是意味着返回一个空类型,这也是为什么你仍然可以在这些函数中使用return语句的原因。只有某些语言中的构造函数和析构函数没有返回值。在这些函数中,不允许使用return语句。它们是显著不同的。Objective-C是一种独特的语言,它的类初始化方法是一种普通的方法,返回值是instancetype(当前类的指针类型)。

Void*可能有点不为人知。void*可以表示C语言中任何类型的指针。说到底,对于一个存储单元的地址来说,它存储的所谓数据类型只是每次取的字节数不一样,这些存储单元的地址本身并没有什么不同。下面会更好的体现这句话的意思。

void*的大小永远是一个字,就像普通的指针一样。具体大小因机器字长而异,例如32位机器为4字节,64位机器为8字节。

我还没有t在16位8086机上验证了指针的大小,因为8086的地址是20位。有兴趣的可以回去试试。个人认为指针大小还是16位,因为20位是物理地址,物理地址是从段地址和偏移地址计算出来的。汇编后,C语言中的指针可能只是变成了相对于段地址的偏移地址。毕竟对于8086来说,数据永远在DS段,而代码永远在CS段。(斜体表示未经核实的陈述)

在C语言中,其他常用类型的指针可以自动转换为void*type,而void*type只能强制转换为其他常用类型的指针,否则会出现警告或错误。

关于所谓的void*指向数组有一个特别大的坑,这里直接用代码解释。

voidSwap(void*array,intx,inty,intmallocsize){

void*tempmalloc(mallocsize)

memcpy(temp,数组mallocsize*x,mallocsize)

memcpy(数组mallocsize*x,数组mallocsize*y,mallocsize)

memcpy(数组mallocsize*y,temp,mallocsize)

免费(临时)

}

这是一个经典的交换函数,借助临时变量temp,不过这个函数是通用的,memcpy的用法后面会介绍。需要注意的是,如果array指向一个数组,你可以t直接用amparray[x]或者arrayx来获取指向x元素的地址,因为void*类型的默认指针偏移量是1,和char*一样,对于大多数类型都会造成错误。因此,在使用泛型类型时,我们必须知道它的原始长度。我们需要一个名为mallocsize的int类型参数来告诉我们这个值,并在计算指针偏移量时乘以它。这相当于C编程中的模板类型定义或者Java中的泛型参数。

同时要注意void*类型的指针,它可以不要在任何时候被取消参考(或者老师过去叫什么"获取内容"在课堂上?),原因很明显:void类型的变量是不合法的。因此,如果要解引用,必须先将其转换成普通指针。当在数组中使用时,还应该注意解引用操作符优先于加法操作符,所以应该加上括号,如下所示:

inta*(数组mallocsize*x)

这段代码完美体现了C语言编程的丑陋。

0x02sizeof运算符简介

Sizeof运算符相信学过C语言的朋友会比较熟悉,但是siZeof是一个运营商,很多人都不知道。返回的类型是size_t类型。sizeof运算符返回类型占用的空间量。这里唯一的要点是,如果你找到一个指针类型或数组名的大小(事实上,数组名是一个指针常量),返回的结果总是一个单词(见上文)。求一个结构类型的sizeof不是简单的结构中各种类型的sizeof之和,而是涉及到内存对齐的问题。我不这里不想介绍了。详情请访问:如何理解struct的内存对齐?-智虎。

0x03memcpy功能简介

Memcpy是一个经常和void*一起使用的函数,它的函数原型是:

void*memcpy(void*,constvoid*,size_t)

头文件属于string.h,可以看到,这个函数本身是以void*type作为参数和返回值的,其实很好理解。这是一个赋值和复制记忆的过程。将第二个参数指向的内存复制到第一个参数,复制的字节数由第三个参数指定。当然,第三个参数通常是通过sizeof运算符获得的,所以我赢了这里就不举例了。我还没有我没有研究过返回值,也没有研究过。;我没用过。如果有知道的朋友可以评论一下。

用0x04C语言实现泛型编程

话虽如此,我们还没有t还没有提到泛型编程。但是,如上所述,一般的思路是使用void*type作为泛型指针,然后使用类似于mallocsize的参数来指定占用的内存大小。占用的内存大小是通过sizeof运算符获得的。如果需要赋值,可以使用memcpy函数来完成。下面是一个直接的例子,这是一个通用的快速排序来说明这些问题:

#ifndefCompare_h

#定义比较_h

#包含ltstdio.hgt

#包含JCB.h

intIsGreater(void*x,void*y)

intIsGreaterOrEqual(void*x,void*y)

intIsSmaller(void*x,void*y)

intIsSmallerOrEqual(void*x,void*y)

#endif

//

//Compare.c

//作业调度程序

//

//鲁创作于2017/11/16。

//版权?2017鲁饶威。全部版权所有。

//

#包含比较.h

intIsGreater(void*x,void*y){

return*(int*)xgt*(int*)y

}

intIsGreaterOrEqual(void*x,void*y){

return*(int*)xgt*(int*)y

}

intIsSmaller(void*x,void*y){

return*(int*)xlt*(int*)y

}

intIsSmallerOrEqual(void*x,void*y){

return*(int*)xlt*(int*)y

}

//

//QuickSort.h

//作业调度程序

//

//鲁创作于2017/11/16。

//版权?2017鲁饶威。保留所有权利。

//

#ifndef快速排序_h

#定义快速排序_h

#包含ltstdio.hgt

#包含ltstdlib.hgt

#包含ltstring.hgt

#包含比较.h

voidQuickSort(void*array,intleft,intright,intmallocsize)

#endif

//

//QuickSort.c

//作业调度程序

//

//鲁创作于2017/11/16。

//版权?2017鲁饶威。保留所有权利。

//

#包含快速排序.h

voidSwap(void*array,intx,inty,intmallocsize){

void*tempmalloc(mallocsize)

memcpy(temp,数组mallocsize*x,mallocsize)

memcpy(数组mallocsize*x,数组mallocsize*y,mallocsize)

memcpy(数组mallocsize*y,temp,mallocsize)

免费(临时)

}

intQuickSortSelectCenter(intl,intr){

返回(左侧)/2

}

intquicksortpartition(void*array,intl,intr,intmallocsize){

intleftl

int右r

void*tempmalloc(mallocsize)

memcpy(temp,数组mallocsize*right,mallocsize)

while(左左右){

while(IsSmallerOrEqual(arraymallocsize*left,temp)ampampleftltright){

左边的

}

if(左lt右){

memcpy(数组mallocsize*right,数组mallocsize*left,mallocsize)

正确

}

while(IsGreaterOrEqual(arraymallocsize*right,temp)ampampleftltright){

正确

}

if(左lt右){

memcpy(数组mallocsize*left,数组mallocsize*right,mallocsize)

左边的

}

}

memcpy(数组mallocsize*left,temp,mallocsize)

向左返回

}

voidQuickSort(void*array,intleft,intright,intmallocsize){

if(leftgtright){

返回

}

中间中心快速排序选择中心(左,右)

交换(数组、中心、右侧、mallocsize)

centerQuickSortPartition(数组,左,右,mallocsize)

快速排序(数组,左,中间-1,移动平均llocsize)

快速排序(数组,中心1,右侧,mallocsize)

}

这里有个悬念,明明可以直接比较,何必用很多函数来完成,也就是关于Compare.h使用的问题,答案会在下面揭晓。

0x05泛型的协议问题

刚才那个问题涉及到一个通用的协议问题,我借用了Objective-C的一个概念在这里详细阐述。就像那个问题一样,既然我的快速排序是泛型的,那我怎么保证传入的实际泛型参数一定是可比较的呢?比如很明显int,float,double是可以比较的,我们也理解char使用ASCII编码方案的比较,字符串类型甚至可以比较。但是如何比较其他语言中的对象呢?这是一个问题。在C中,我们可以重载运算符,所以我们仍然可以使用比较运算符,并使用运算符来重载函数。但是Java和Objective-C呢?而如果传入的泛型参数没有实现对应的运算符重载函数呢?这时,有必要引入一个协议的概念。简单地说,如果一个类型想要成为一个排序泛型函数的泛型参数,你必须实现一个可比较的协议。这个协议在Swift语言中叫做Comparable,这样在编译的时候,编译器就会知道这个泛型参数是可以比较的,从而完成我们的操作,否则就会出错。这是泛型中的协议问题。

0x06摘要

C语言的泛型编程以void*为泛型类型,本质上是一个泛型指针。

C语言中的泛型编程需要知道泛型类型变量的内存大小,这可以通过sizeof获得并传递给泛型函数。

在C语言的泛型编程中,要注意数组的偏移量。void*的默认偏移量是1,对于大多数类型来说是错误的,需要自己编程转换。

Memcpy函数用于在C语言的泛型编程中复制和赋值泛型变量。

在C语言的泛型编程中,我们也需要注意协议问题,但是在C中,我们只能自己编写函数来定义,可以使用其他语言现成的接口或协议。

 
反对 0举报 0 收藏 0 打赏 0评论 0
 
更多>同类资讯
推荐图文
推荐资讯
点击排行
合作伙伴
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报  |  冀ICP备2023006999号-8