2016 - 2024

感恩一路有你

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

浏览量:1059 时间:2023-03-30 22:15:04 作者:采采

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

冒泡排序是一种常见的排序方法,反复访问要排序的元素,依次比较相邻的两个元素,如果前面大于后面就交换。用C语言实现冒泡排序时,需要使用两个循环。对于n个元素的数组A,外循环I的取值范围为0到n-1,内循环J的取值范围为0到n-1-i,若A [j] GTA [j 1],则两个元素互换,直到循环结束,此时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 *指向数组有一个特别大的坑,这里直接用代码解释。

void Swap(void *array,int x,int y,int mallocsize) {

void *temp malloc(mallocsize)

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

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

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

免费(临时)

}

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

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

int a *(数组mallocsize * x)

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

0x02 sizeof运算符简介

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

0x03 memcpy功能简介

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

void * memcpy(void *,const void *,size_t)

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

用0x04 C语言实现泛型编程

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

#ifndef Compare_h

#定义比较_h

#包含ltstdio.hgt

#包含JCB.h

int IsGreater(void *x,void *y)

int IsGreaterOrEqual(void *x,void *y)

int IsSmaller(void *x,void *y)

int IsSmallerOrEqual(void *x,void *y)

#endif /* Compare_h */

//

// Compare.c

//作业调度程序

//

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

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

//

#包含比较. h

int IsGreater(void *x,void *y) {

return *(int *)x gt *(int *)y

}

int IsGreaterOrEqual(void *x,void *y) {

return *(int *)x gt *(int *)y

}

int IsSmaller(void *x,void *y) {

return *(int *)x lt *(int *)y

}

int IsSmallerOrEqual(void *x,void *y) {

return *(int *)x lt *(int *)y

}

//

// QuickSort.h

//作业调度程序

//

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

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

//

#ifndef快速排序_h

#定义快速排序_h

#包含ltstdio.hgt

#包含ltstdlib.hgt

#包含ltstring.hgt

#包含比较. h

void QuickSort(void *array,int left,int right,int mallocsize)

#endif /* QuickSort_h */

//

// QuickSort.c

//作业调度程序

//

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

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

//

#包含快速排序. h

void Swap(void *array,int x,int y,int mallocsize) {

void *temp malloc(mallocsize)

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

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

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

免费(临时)

}

int QuickSortSelectCenter(int l,int r) {

返回(左侧)/2

}

int quick sort partition(void * array,int l,int r,int mallocsize) {

int left l

int右r

void *temp malloc(mallocsize)

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

while(左左右){

while(IsSmallerOrEqual(array mallocsize * left,temp) ampamp left lt right) {

左边的

}

if(左lt右){

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

正确

}

while(IsGreaterOrEqual(array mallocsize * right,temp) ampamp left lt right) {

正确

}

if(左lt右){

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

左边的

}

}

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

向左返回

}

void QuickSort(void *array,int left,int right,int mallocsize) {

if (leftgtright) {

返回

}

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

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

center QuickSortPartition(数组,左,右,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中,我们只能自己编写函数来定义,可以使用其他语言现成的接口或协议。

类型 指针 函数 参数 mallocsize

版权声明:本文内容由互联网用户自发贡献,本站不承担相关法律责任.如有侵权/违法内容,本站将立刻删除。