c语言函数怎么改变实参的值自定义函数实参?

24.1.普通变量作为函数形参 (1)普通变量作为参数在函数传参时,形参和实参名字可以相同也可以不同,实际上都是用实参来替代相应的形参的。 (2)在字函数内部,形参的值等于实参。原因是函数调用时把实参的值赋值给了形参。这就是所谓的”传值调用”,相当于实参做右值,形参做左值。


24.2.数组和指针作为函数形参 (1)函数名作为形参传参时,实际传递是不是整个数组,而是数组的首元素的首地址。所以在子函数内部,传进来的数组名就等于是一个指向数组首元素首地址的指针。所以sizeof得到的是4。 (2)在子函数内传参得到的数组首元素首地址,和外面得到的数组首元素首地址是相同的。这就是所谓的”传址调用”,即调用子函数时传了地址,此时可通过传进去的地址访问实参。 (3)数组名作为函数形参时,[]里的数字可有可无。因为数组名做为形参传递的实际只是个指针,根本没有数组长度这个信息。 (4)指针作为函数形参时和数组作为函数形参是一样的.这就好像指针方式访问数组元素和数组方式访问数组元素的结果一样是一样的。


24.3.结构体变量作为函数形参 (1)结构体变量作为函数形参的时候,实际上和普通变量(类似于int之类的)传参时表现是一模一样的。所以说结构体变量其实也是普通变量而已。 (2)因为结构体一般都很大,所以如果直接用结构体变量进行传参,那么函数调用效率就会很低。(因为在函数传参的时候需要将实参赋值给形参,所以当传参的变量越大调用效率就会越低)。为提高效率,我们可改传变量的指针(地址)进去。 (3)结构体因为自身太大,所以传参应该用指针来传(但是程序员可以自己决定,你非要传结构体变量过去C语言也是允许的,只是效率低了)。


24.4.传值调用与传址调用 (1)传值调用描述的是这样一种现象:x和y作为实参,自己并没有真身进入swap1函数内部,而只是拷贝了一份自己的副本(副本具有和自己一样的值,但是是不同的变量)进入子函数swap1,然后我们在子函数swap1中交换的实际是副本而不是x、y真身。所以在swap1内部确实是交换了,但是到外部的x和y根本没有受影响。 (2)在swap2中x和y真的被改变了(但是x和y真身还是没有进入swap2函数内,而是swap2函数内部跑出来把外面的x和y真身改了)。实际上实参x和y永远无法真身进入子函数内部(进去的只能是一份拷贝),但是在swap2我们把x和y的地址传进去给子函数了,于是乎在子函数内可以通过指针解引用方式从函数内部访问到外部的x和y真身,从而改变x和y。 (3)结论:这个世界上根本没有传值和传址这两种方式,C语言本身函数调用时一直是传值的,只不过传的值可以是变量名,也可以是变量的指针。 


24.5.函数形参和返回值 (1)函数名是一个符号,表示整个函数代码段的首地址,其实质是一个指针常量,所以在程序中使用到函数名时都是当地址用的,表示调用该函数。函数体是函数的关键,由一对{}括起来,包含很多句代码,函数体就是函数实际做的工作。形参列表和返回值,形参是函数的输入部分,返回值是函数的输出部分。 (2)若没有形参列表和返回值,函数也能对数据进行加工,使用全局变量即可。用全局变量来传参和用函数参数列表返回值来传参各有特点,在实践中都有使用。总的来说,函数参数传参用得较多,因为这样可实现模块化编程,而C语言中也是尽量减少使用全局变量。 (3)全局变量传参最大的好处就是省略了函数传参的开销,所以效率要高一些;但是实战中用的最多的还是函数传参,如果参数很多传参开销非常大,通常的做法是把很多参数打包成一个结构体,然后传结构体变量指针进去。


24.6.函数传参中使用const指针 (1)const用来修饰指针作函数传参,就是为了声明在函数内部不会改变该指针所指向的变量。所以给该函数传一个不可改变的指针(譬如char *p = “linux”; 字符串常量,放在代码段中,不可改变)后,一旦该函数内部试图更改它时编译器会提示错误;而一个未声明为const指针参数的函数,我们给该函数传一个不可更改的指针时,一旦该函数内部更改它后,编译器在编译过程中不会有提示,而是会在运行中导致段错误。 (2)一般来说,函数的输入部分就是函数参数,输出部分就是返回值。问题是函数的参数可以有很多个,而返回值只能有一个。则我们无法让一个函数返回多个值。 (3)现实编程中,一个函数需要返回多个值是非常普遍的,因此完全依赖于返回值是不靠谱的,通常的做法是用参数来做返回(在典型的linux风格函数中,返回值是不用来返回结果的,而是用来返回0或者负数用来表示程序执行结果是对还是错,是成功还是失败)。 (4)普遍做法,编程中函数的输入和输出都是靠函数参数的,返回值只是用来表示函数执行的结果是对(成功)还是错(失败)。如果这个参数是用来做输入的,就叫输入型参数;如果这个参数的目的是用来做输出的,就叫输出型参数。输出型参数就是用来让函数内部把数据输出到函数外部的。 (5)总结:函数传参如果传的是普通变量(不是指针)那肯定是输入型参数;若该函数形参是指针变量并且加了const,那么就表示这个参数是用来做输入型参数的;若该函数形参是指针变量并且还没加const,那么就表示这个参数是用来做输出型参数的。譬如C库函数中strcpy函数:char *strcpy(char *dest, const char *src);。

内容来源于网络如有侵权请私信删除

  • 害,菜鸡真的是走一步一个坑,有时间一定得系统学习一下c了。

    言归正传,给函数传递二位数组,我目前可以掌握的有三种方法:

    1.将二维数组压缩成一维数组,然后就可以正常用指针了,用的时候注意一下二维与一维的坐标变换就可以;(我没用,因为我代码已经写好了,不想改!)

    2.传二维数组,如 short gmmse(short H[4][4]),这种用起来也没问题,传入的数据可以正常被修改;

    我目前使用的是3。然后我就在思考2、3的区别,哪一个是最推荐的,或者说性能最好的。目前只看到一类解释,使用指针更节省堆栈。因为指针传进去的是一个地址(这个很好理解)。数组传进去的其实好像也是地址。哈哈。

    但是数组使用的是连续的空间,一般存在静态区或者栈。

    所以问题或者说关键在于,最开始定义的时候,数组使用的是连续内存空间,而给指针分配空间的时候,可以是分散的。

  • 话题:C语言函数调用维数组,指针问题回答:正如楼下所言 int **p ,定义的p是个指向int*型的指针int (*p)[1]是个指向数组的指针 数度为1假如定义成 deal(int **p),传参数时要加类型转换: deal((int**)a);...

    话题:C语言函数调用二维数组,指针问题回答:正如楼下所言 int **p ,定义的p是一个指向int*型的指针int (*p)[1]是一个指向数组的指针 数度为1假如定义成 deal(int **p),传参数时要加类型转换: (*p)[1])就不一样了,编译器就能知道p是一个指向长度为1的数组的指针那么p[2][3]就能编译成*(p+2*1+3)了总之,C语言是很灵活的,不同的定义方式配上不同的用法,都是能得到正确的结果的不知道这么说楼主明白了没?同样的还有多维数组对多维指针的问题,楼主可以自己类推一下

    参考回答:int **p是指向int*的指针,int(*p)[1] 是指向数组的指针话题:c语言中怎么用二维数组作为函数参数回答:C语言中 指针做函数参数传递二维数组有两种基本方法:1、传递“数组指针”#include void output( int (*pa)[3], int n ) 这个函数只能输出n行3列的二维数组{int i,j;for( )[N]类型的指针,其中N是二维数组第2维的长度,如果还不懂可以追问我改成这样就可以了:#include话题:C语言问题,请问二维数组的函数参数是怎么传递的?回答:在形参是数组的情况下,只要是数组,无论维数,实际上在调用函数时,传给函数的将是一个数组的首,以及维数等相关也就是说,在函数执行过程中,并不会新开辟内存空间,而是形参实参共用同一段内存空间所以,在这种情况下,函数内部对数组进行修改,其值会返回给实参你的例中调用部分有问题,不能这样shuru(a[1][2])而是shuru(a)因为a[1][2]数组a中的一个元素,而且是越界的而a才是数组名

    也是一样,望采纳,如有不明白请追问谢谢!话题:C语言怎么用指针替二维数组回答:设二维数组为typename a[M][N],则指向该数组的指针为typename (*p)[N] = a;这样就可以用p来替二维数组了。

    调用就直接加数字,该数字是lt;3*3的就行}话题:C语言怎么以二维数组作为参数传递的问题回答:考虑要把a作为参数传入到print中,那么print函数就要定义一个接收二维数组的参数,那么什么参数能接收二维数组呢。就是print(int (*newbuf)[3])然后newbuf的就是a的,然后newbuf[i][j]来访问每一个元素了有问题继续问哈,写的可

    参考回答:展开全部 考虑要把a作为参数传入到print中,那么print函数就要定义一个接收二维数组的参数,那么什么参数能接收二维数组呢。就是print(int (*newbuf)[3])然后newbuf的就是a的,然后newbuf[i][j]来访问每一个元素了有问题继续问哈,写的可能不太明白话题:c语言问题,用指针为一个二维数组赋值回答:pptr=arr;/p p其实你这样赋值也是可以的,是没有问题的。/p p因为arr是二维数组的数组名,它(arr)本身就这个二维数组的第行的。/p p问题关键不是出现在这里,而是在你程序的while循环语句中/p pwhile(scanf("%f", ptr+i)i!=)/p pi++;/p p你这样写是不对的,首先ptr指向的是一个,所以ptr+i也是一个,所以这里就不能用变址运算符""了。第二个问题是,i 从自加到6,这里面其实有了个数,明显超过了arr数组的长度,这样是不对的。这个循环还有一个问题就是,这本身就是一个不正常的循环(自己想想为什么)/p p下面是我帮你改改的码,希望对你会有帮助。/p p#includestdio.h/p pvoid p/p话题:C语言中指针引用二维数组元素的问题回答:二维数组名a是一个指向指针的指针。也是一个指针数组名,它含3个元素,a[]a[1],a[2]。虽然a存储的是该数组首元素的,但它指向的并不是一个变量,而是一个指针。应为a是一个指向指针的指针,它指向的是和自己存储的相同的指针,即a[],a[]是第一行一维数组的指针,可以指向具体变量。这下明白了吧,*(a+)它不是变量,她是指针,a指向a[],*(a+)就是a[].

    参考回答:呵呵,我也刚学到这个问题,和你分享一下吧,咋看之下,确实像你说的没错,但是这个“[]”运算符和“*()”运算符原来是一个意思的,是不是因为搬到二维数组就混淆了呀,我原来也是有同样的问题的。你看看哪,要是搬回一维数组的话,我们知道a[]与*(a+)是相等的.然后我们再回到二维数组讨论讨论,我认为既然a[][]是二维数组,(a+)怎么看也不可能是二维吧,所以再用“星号”*去取里边的值,换是你,你该怎么取呢?所以呢,它们是相同的应该没错才对,是不是?话题:c语言问题,用指针为一个二维数组赋值回答:pptr=arr;/p p其实你这样赋值也是可以的,是没有问题的。/p p因为arr是二维数组的数组名,它(arr)本身就这个二维数组的第行的。/p p问题关键不是出现在这里,而是在你程序的while循环语句中/p pwhile(scanf("%f", ptr+i)i!=)/p pi++;/p p你这样写是不对的,首先ptr指向的是一个,所以ptr+i也是一个,所以这里就不能用变址运算符""了。第二个问题是,i 从自加到6,这里面其实有了个数,明显超过了arr数组的长度,这样是不对的。这个循环还有一个问题就是,这本身就是一个不正常的循环(自己想想为什么)/p p下面是我帮你改改的码,希望对你会有帮助。/p p#includestdio.h/p pvoid p/p话题:c语言,指向二维数组的指针变量回答:先从存储的角度对二维数组作一个全面的了解。二维数组在内存中的存储,是按照先行后列依次存放的。从内存的角度看,可以这样说,二维数组其实就是一个一维数组,在内存中没有二维的概念。如果把二维数组的每一行看成一个整体,即看成一个数组中的一个元素,那么整个二维数组就是一个一维数组,它以每一行作为它的元素,这个应该很好理解。第一,来详细介绍二维数组与指针的。- 首先定义个二维数组 array[3][4],p 为指向数组的指针。若p=array[],此时p指向的是二维数组第一行的首,则 p+i 将指向array[]数组中的元素array[][i]。由以上所介绍的二维数组在内存中的存储方式可知,对数组中的任一元素array[i][j] ,其指针的形式为:p+i*N+j (N为每一行的长度)。 下标表示法为:array[2*3+2] 。特别注意:虽然 array[] 与 array 都是数组首,但两者指向的对象不同,这点要非常明确。array[] 是一维数组的名字,它指向的是一维数组array[]的首,所以 *array[]与array[][]为同个值。而 array 是二维数组的名字,它指向的是所属元素的首,其每个元素为一个行数组。它是以‘行’来作为指针移动单位的,如array+i 指向的是第 i 。注意:数组名虽然是,但与指向数组的指针质不同。指针变量可以随时改变其所指向对象,而数组名不可以,一旦被定义,就不能通过赋值使其指向另外一个数组,但是在Ja中则可以。第三,顺便了解一下不太常用的‘行数组指针’。对于二维数组array[4][3],与int* p 。二维数组名array 不能直接赋值给p。原因前面已讲过,两只的对象质不同。 在C语言中,可以通过定义一个行数组指针,使得这个指针与二维数组名具有同样的质,实现它们之间可以直接赋值。行数组指针定义如下:int (*p)[3]; 它表示,数组 *p 具有三个int类型元素,分别为 (*p)[] , (*p)[1] , (*p)[2] ,即 p指向的是具有三个int类型的一维数组,也就是说,p为行指针。此时,以下运算 p=array 当二维数组名作为函数实参时,对应的形参必须是一个行指针变量。和一维数组一样,数组名传送给变量的是一个值,因此,对应的形参也必须是一个类型相同的指针变量,在函数中引用的将是主函数中的数组元素,系统只为形参开辟一个存放的存储单元,而不可能在调用函数时为形参开辟一系列存放数组的存储单元。int main() double a[3][4]; …… fun(a); ……

  • 如何定义和引用一维数组 1.数组是一组有序数据的集合,下标代表数据在数组中的序号 2.用一个数组名和下标来唯一地确定数组中的元素,如S15代表第十五个学生成绩 3.数组中的每一个元素都属于同一种数据类型,不能把...

    如何定义和引用一维数组

    1.数组是一组有序数据的集合,下标代表数据在数组中的序号
    2.用一个数组名和下标来唯一地确定数组中的元素,如S15代表第十五个学生成绩
    3.数组中的每一个元素都属于同一种数据类型,不能把不同类型的数据放在同一个数组中。

    一.怎么定义和引用一维数组

    1.1怎样定义一维数组

    它代表定义了一个整型数组,数组名为a,此数组包含了十个整形元素。

    定义一维数组的一般形式为:
    类型说明符 数组名[常量表达式]

    1.数组名的命名规则和变量名相同,遵循标识符命名规则。
    2.在定义数组时,需要指定数组中元素的个数,方括号中的常量表达式用来表示元素的个数,即数组长度,例如a[10],表示a数组中有10个元素。,需要注意的是下标是从0开始的,不存在数组元素a[10].
    3.常量表达式中可以包括常量和符号常量,,如"int a[3+5] "是合法的。不能包含变量,如 “int a[n] ”,这是不合法的。C语言不允许对数组的大小做动态定义。,即数组的大小不依赖于程序运行过程中变量的值,例如下面的数组定义是不合法的:

    1.2如何引用一维数组

    在定义数组并对其中各元素赋值后,就可以引用数组中的元素。应注意只能引用数组元素而不能一次整体调用整个数组全部元素的值。
    引用数组元素的表示形式

    定义数组时用到的"数组名[常量表达式]“和引用数组元素时用的"数组名[下标]” 形式相同,但含义不同,例如:

    1.3一维数组的初始化

    为了使程序简洁,常在定义数组的同时给各数组元素赋值,这称为数组的初始化。可以用“初始化列表”方法实现数组的初始化。
    (1).在定义数组时对全部数组元素赋予初值,例如:

    将数组中各元素的初值顺序放在一对花括号内,数据间用逗号隔开。花括号内的数据就称为“初始化列表”。
    (2).可以只给数组中的一部分元素赋值,例如:

    定义a数组有10个元素,但花括号内只提供五个初值,这表示只给前面五个元素赋初值,系统自动给后五个元素赋初值为0;
    (3).如果想要使一个数组中全部元素值为0,可以写成

    (4).在对全部数组元素赋初值时,由于数据的个数已经确定,因此可以不指定数组长度,例如:

    在第2种写法中,花括号中有5个数,虽然没有在主括号中指定数组的长度,但是系统会根据花括号中数据的个数确定a数组有五个数组。但是,如果数组长度与提供初值的个数不相同,则方括号中的数组长度不能省略。例如,想定义数组长度为10,就不能省略数组长度的定义,而必须写成:

    只初始化了前面五个元素,后五个元素为0.

    如果在定义数值型数组时,指定了数组的长度并对之初始化,凡未被"初始化列表"指定初始化的数组元素,系统会自动把它们初始化为0(如果是字符型数组,则初始化为’\0’),如果是指针型数组,则初始化为NULL,即空指针。

  • C语言中,在子函数中将个二维数组返回 都知道,在子函数中,一定不能返回个局部变量的指针,局部变量在子函数中进行创建,子函数调用结束后,该指针将被释放掉。 如果被指针所指向的该内存空间被别的程序占用着...

    都知道,在子函数中,一定不能返回一个局部变量的指针,局部变量在子函数中进行创建,子函数调用结束后,该指针将被释放掉。
    如果被指针所指向的该内存空间被别的程序占用着,由于指针已将被释放掉了,结果在后续程序中还接着用该指针,就会造成程序崩溃。

    这里用字符型二维数组举例来讨论

    将这个三行三列的整形数组从子函数中创建出来,在主函数中进行遍历,将所有的元素打印出来

    直接在子函数中定义二维数组,把二维数组数组名直接返回,行不行?

    通过编译,这样是错误的,我们也能分析到,局部变量在子函数调用结束后指针,也就是这个Arr所保存的地址就被释放掉了,是非法的

    这里可以通过Malloc函数,开辟内存空间,将数组地址就可以通过子函数来进行返回,在主函数中进行遍历了。

    // 将保存每一行的指针先释放掉 // 最后将保存整个二维数组的指针释放掉

    对于二维数组通过Malloc进行创建的讨论


    先在内存中开辟三个大小为sizeof(char *)的空间,因为每一个sizeof(char *)大小的空间存放的都是指向字符串的指针,类型为char *
    再通过for循环,对每一个char *指针所指向的字符串的空间进行开辟,通过Brr数组对其内容进行赋值即可。
    这样返回的指针在主函数中进行遍历输出就可以了。
    这里还是需要注意,在遍历二维数组时,搞清楚指针的指向情况

  • 很多人都遇到过函数不能接收二维数组的问题,网上的很多方法都特别麻烦。那么,有没有一种办法,可以像传一维数组那样传二维数组呢?有的。如果不想看分析的话,可以直接在目录中点“总结”...

  • 以前就知道C语言的二维数组在内存中是一维数组进行存储的,但是没有试过使用一维数组对二维数组进行调用。原以为编译会报错,但实际上没有报错。

  • 数组 1.数组的定义: 2.C语言规定:数组的每个元素都有下标,且下标是从0开始的。 3.数组的使用 4.数组使用时可能出现的错误 越界访问: 经典题型 5.判断两个数组类型是否相同: ...

  • 今天写程序的时候要用到二维数组作参数传给一个函数,我发现将二维数组作参数...可以用二维数组名作为实参或者形参,在被调用函数中对形参数组定义时可以指定所有维数的大小,也可以省略第一维的大小说明,如: voi

  • 可以用二维数组名作为实参或者形参,在被调用函数中对形参数组定义时可以指定所有维数的大小,也可以省略第一维的大小说明,如: void Func(int array[3][10]); void Func(int array[][10]); 二者都是合法而且等价,...

  • 之前在学习二维数组的时候感觉理解起来很简单,... 函数调用维数组 在函数中调用二维数组的具体格式如下:1、声明:这是声明的两种格式,在这里定义的是个N*5的二维字符数组,各位看官一定要注意,在声...

  • 给定数组,利用函数将其逆序,并利用函数打印出该数组 思想:利用空瓶子思想,创建个临时变量来交换数组中的元素, 注意:在进行交换变量时,写赋值语句时,tem注意不要写成数组名【tem】,楼主当时在这里写错...

  • 今天复习到c语言数组,看到这么个问题:现在,你的程序要读入两个多项式,然后输出这两个多项式的和,也就是把对应的幂上的系数相加然后输出。程序要处理的幂最大为100。输入格式:总共要输入两个多项式,每个...

  • C语言设计4个自定义函数,实现对一维数组的排序、查找、插入和删除操作,并在主调函数中设计switch结构进行具体功能函数的选择调用

  • 可以定义个能接受数组作为函数参数的函数,然后调用这个函数时,可以将个实际的数组传递给它。 数组作为函数参数时,其定义方式有下列三种:

  • 数组函数 数组 数组是有序的元素序列,简单点说就是存放数据的容器;数组一旦创建是不可更改的;数组中的元素在内存中是连续依次排列的。 如 int a[100]; 表示定义了个有100个单元的数组a。即a[0] a[1]

  • C语言维数组的传参与调用 数组名的含义 二维数组的存储方式

  • 其基本概念与方法与一维数组相似,如: float pay[3][6]; 以上定义了一个float型的二维数组 第一维有3个元素,第二维有6个元素。每一维的长度分别用一对括号起来 二维数组定义的一般形式为 类型说明符 数组名 [常量...

我要回帖

更多关于 c语言函数怎么改变实参的值 的文章

 

随机推荐