精华内容
下载资源
问答
  • 对于void函数调用时不可作为
    千次阅读
    2021-05-20 18:59:40

    许多初学者对C/C++语言中的void及void指针类型不甚理解,因此在使用上出现了一些错误。下面小编就跟大家介绍下c语言void的用法。

    c语言void的用法1.void的含义

    void的字面意思是“无类型”,void*则为“无类型指针”,void*可以指向任何类型的数据。

    void几乎只有“注释”和限制程序的作用,因为从来没有人会定义一个void变量,让我们试着来定义:

    voida;

    这行语句编译时会出错,提示“illegaluseoftype'void'”。不过,即使voida的编译不会出错,它也没有任何实际意义。

    void真正发挥的作用在于:(1)对函数返回的限定;(2)对函数参数的限定。

    我们将在第三节对以上二点进行具体说明。

    众所周知,如果指针p1和p2的类型相同,那么我们可以直接在p1和p2间互相赋值;如果p1和p2指向不同的数据类型,则必须使用强制类型

    转换运算符把赋值运算符右边的指针类型转换为左边指针的类型。

    例如:float*p1;int*p2;p1=p2;

    其中p1=p2语句会编译出错,提示“'=':cannotconvertfrom'int*'to'float*'”,必须改为:p1=(float*)p2;而void*则不同,任何类型的指针都可以直接赋值给它,无需进行强制类型转换:void*p1;int*p2;p1=p2;

    但这并不意味着,void*也可以无需强制类型转换地赋给其它类型的指针。因为“无类型”可以包容“有类型”,而“有类型”则不能包

    容“无类型”。道理很简单,我们可以说“男人和女人都是人”,但不能说“人是男人”或者“人是女人”。下面的语句编译出错:void*p1;int*p2;p2=p1;

    提示“'=':cannotconvertfrom'void*'to'int*'”。

    c语言void的用法2.void的使用

    下面给出void关键字的使用规则:

    规则一如果函数没有返回值,那么应声明为void类型

    在C语言中,凡不加返回值类型限定的函数,就会被编译器作为返回整型值处理。但是许多程序员却误以为其为void类型。例如:add(inta,intb){

    returna+b;}

    intmain(intargc,char*argv[]){

    printf("2+3=%d",add(2,3));}

    程序运行的结果为输出:2+3=5

    这说明不加返回值说明的函数的确为int函数。

    林锐博士《高质量C/C++编程》中提到:“C++语言有很严格的类型安全检查,不允许上述情况(指函数不加类型声明)发生”。可是编译

    器并不一定这么认定,譬如在VisualC++6.0中上述add函数的编译无错也无警告且运行正确,所以不能寄希望于编译器会做严格的类型检查。

    因此,为了避免混乱,我们在编写C/C++程序时,对于任何函数都必须一个不漏地指定其类型。如果函数没有返回值,一定要声明为void类

    型。这既是程序良好可读性的需要,也是编程规范性的要求。另外,加上void类型声明后,也可以发挥代码的“自注释”作用。代码的“自注

    释”即代码能自己注释自己。

    规则二如果函数无参数,那么应声明其参数为void

    在C++语言中声明一个这样的函数:intfunction(void){

    return1;}

    则进行下面的调用是不合法的:function(2);

    因为在C++中,函数参数为void的意思是这个函数不接受任何参数。

    我们在TurboC2.0中编译:#include"stdio.h"fun(){

    return1;}

    main(){

    printf("%d",fun(2));getchar();}

    编译正确且输出1,这说明,在C语言中,可以给无参数的函数传送任意类型的参数,但是在C++编译器中编译同样的代码则会出错。在C++

    中,不能向无参数的函数传送任何参数,出错提示“'fun':functiondoesnottake1parameters”。

    所以,无论在C还是C++中,若函数不接受任何参数,一定要指明参数为void。

    规则三小心使用void指针类型

    按照ANSI(AmericanNationalStandardsInstitute)标准,不能对void指针进行算法操作,即下列操作都是不合法的:void*pvoid;

    pvoid++;//ANSI:错误pvoid+=1;//ANSI:错误

    //ANSI标准之所以这样认定,是因为它坚持:进行算法操作的指针必须是确定知道其指向数据类型大小的。//例如:pint++;//ANSI:正确

    pint++的结果是使其增大sizeof(int)。(在VC6.0上测试是sizeof(int)的倍数)

    但是大名鼎鼎的GNU(GNU'sNotUnix的缩写)则不这么认定,它指定void*的算法操作与char*一致。

    因此下列语句在GNU编译器中皆正确:pvoid++;//GNU:正确pvoid+=1;//GNU:正确

    pvoid++的执行结果是其增大了1。(在VC6.0上测试是sizeof(int)的倍数)

    在实际的程序设计中,为迎合ANSI标准,并提高程序的可移植性,我们可以这样编写实现同样功能的代码:void*pvoid;

    (char*)pvoid++;//ANSI:正确;GNU:正确(char*)pvoid+=1;//ANSI:错误;GNU:正确

    GNU和ANSI还有一些区别,总体而言,GNU较ANSI更“开放”,提供了对更多语法的支持。但是我们在真实设计时,还是应该尽可能地迎合

    ANSI标准。

    规则四如果函数的参数可以是任意类型指针,那么应声明其参数为void*

    典型的如内存操作函数memcpy和memset的函数原型分别为:void*memcpy(void*dest,constvoid*src,size_tlen);void*memset(void*buffer,intc,size_tnum);

    这样,任何类型的指针都可以传入memcpy和memset中,这也真实地体现了内存操作函数的意义,因为它操作的对象仅仅是一片内存,而不

    论这片内存是什么类型。如果memcpy和memset的参数类型不是void*,而是char*,那才叫真的奇怪了!这样的memcpy和memset明显不是一个

    “纯粹的,脱离低级趣味的”函数!

    下面的代码执行正确:

    //示例:memset接受任意类型指针intintarray[100];

    memset(intarray,0,100*sizeof(int));//将intarray清0

    //示例:memcpy接受任意类型指针intintarray1[100],intarray2[100];

    memcpy(intarray1,intarray2,100*sizeof(int));//将intarray2拷贝给intarray1

    有趣的是,memcpy和memset函数返回的也是void*类型,标准库函数的编写者是多么地富有学问啊!

    规则五void不能代表一个真实的变量

    下面代码都企图让void代表一个真实的变量,因此都是错误的代码:voida;//错误

    function(voida);//错误

    void体现了一种抽象,这个世界上的变量都是“有类型”的,譬如一个人不是男人就是女人(还有人妖?)。

    void的出现只是为了一种抽象的需要,如果你正确地理解了面向对象中“抽象基类”的概念,也很容易理解void数据类型。正如不能给抽

    象基类定义一个实例,我们也不能定义一个void(让我们类比的称void为“抽象数据类型”)变量。

    4.总结

    小小的void蕴藏着很丰富的设计哲学,作为一名程序设计人员,对问题进行深一个层次的思考必然使我们受益匪浅。

    -------------------------------------------//下面自己整理了点

    不论什么类型的指针(void*,char*,int*,float*...)默认初始值都是0xCCCCCCCC

    #include#include//#includevoidmain(){

    void*p1;inta=10;int*p2=&a;

    cout<

    cout<

    cout<

    }

    /*输出:

    0xCCCCCCCC0x0012FF780x0012FF780x0012FF78*/

    在声明同时赋值NULL,在delete后立即设置为NULL。

    在debug版本下指针默认初始值为0xCCCCCCCC,在Release版本下初始值为0x0000000A,(在我电脑上VC6.0)。对于指针如果暂时没有合适的初始化值,就应该把它置为NULL(0)。对于好的编程习惯来说,declare一个指针,则初始化为NULL,如果是类成员则在构造函数中initialize,当对指针使用delete时候,则置它为NULL.

    0xCCCCCCCC只是在debug状态下VC生成的未定义过的指针值,用来提示这个指针是未被初始化的,在release状态下不会等于这个值(除非巧合)。对于指针如果暂时没有合适的初始化值,就应该把它置为NULL(0)。

    更多相关内容
  • 对于void类型函数调用时不可作为

    千次阅读 2021-05-21 02:33:34
    c语言 void函数怎么调用当n=123114350, 结果为:c1=3 c2=1 c3=2 int c1, c2, c3; void fun(lon【void的含义】 void的字面意思是“无类型”,void *则为“无类型指针”,void *可以指向任何类型的数据。 void几乎...

    c语言 void函数怎么调用

    当n=123114350时, 结果为:c1=3 c2=1 c3=2 int c1, c2, c3; void fun(lon【void的含义】 void的字面意思是“无类型”,void *则为“无类型指针”,void *可以指向任何类型的数据。 void几乎只有“注释”和限制程序的作用,因为从来没有人会定义一个void变量, void真正发挥的【作用】在于: (1) 对函数返回的限定; (2)

    main 函数的返回值用于说明程序的退出状态。如果返回 0,则代表程序正常退出,否则代表程序异常退出。 在 C89中,main() 是可以接受void返回值的。在最新的 C99 标准中,只有以下两种定义方式是正确的: int main( void ) int main( int argc, c

    2c4558f50da9c3d79a2181dfe9da6b0e.png

    函数调用前加(void)作用

    关于Void*调用函数的疑惑?int plus(int b) { return b+1; } int main() { void* pV = NULL;//定义int(*)(int)表示一个函数指针,它指向一个拥有一个int参数的、返回值为int型的函数。 void*指针可以强制转换成其他任何指针。

    对于void类型函数调用时不可作为

    函数的定义程序 void Wr24LCxx(U8 slvAddr,U8 addr,U8 data)。。。。

    设在主函数中有以下定义和函数调用语句,且 fun 函设在主函数中有以下定义和函数调用语句,且 fun 函数为 void 类型;请写void fun(double[][22] b);二维数组作为参数必须写明除第一维外的其它维数

    对于void类型函数,调用时不可作为()。 A:自定义函对于void类型函数,调用时不可作为()。 A:自定义函数体中的语句 B:循环体A肯定可以 B肯定可以 C不太明白什么是if的成分语句?if的条件吗,如果是,就不可以,因为void型函数没有返回值 D表达式中间肯定不行,单独void 函数调用作为表达式语句可以。

    展开全文
  • 将数组作为函数参数调用

    千次阅读 2021-10-15 14:40:41
    数组作为参数在函数中被调用的写法

    数组与单个元素一样,也可以作为参数被函数调用,但其用法与单个元素调用存在不同。

    对于单个元素调用,如不使用引用&或者指针,则在函数中对形参的操作不会反映到实参上,即实参不会发生改变,具体用法详见上一篇博客。

    而对于数组调用,函数的形参看似是一个新的数组,但并未分配新的内存。因为数组的名字代表着数组的首地址。因此**在数组名作函数参数时所进行的传送只是地址的传送,也就是说把实参数组的首地址赋予形参数组名。**形参数组名取得该首地址之后,也就等于有了实在的数组。实际上是形参数组和实参数组为同一数组,共同拥有一段内存空间。
    在这里插入图片描述
    因此,形参数组是一个虚拟数组,其数组的地址指向了实参数组。如a[0]与b[0]都指向了同一个地址。在对形参数组进行操作时,实参数组的值也会相应的发生改变。

    在函数调用数组的方法
    1.对于一维数组:

    void invert(int x[]){
    	//函数部分 
    }
    int main(){
    	int a[10];
    	invert(a);
    	//主函数调用部分 
    }
    

    注:
    1.形参与实参的类型必须一样,如int对应int。
    2.主函数调用invert函数时只需使用实参数组的名字,代表数组的地址。
    3.形参数组可以不规定长度,但实参数组会规定长度。

    另一种写法:

    void invert(int x[10]){
    	//函数部分 
    }
    int main(){
    	int a[10];
    	invert(a);
    	//主函数调用部分 
    }
    

    可以规定好形参数组的长度。但由于形参数组是虚拟数组,其地址与实参数组的地址对应,故形参数组的长度其实并无太大意义。

    void invert(int x[110]){
    	//函数部分 
    	for(register int i=1;i<=100;i++){
    		x[i]=0;
    	} 
    }
    int main(){
    	int a[10];
    	invert(a);
    	//主函数调用部分 
    }
    

    若形参数组长度大于实参数组,则可能导致对形参数组的部分操作没有意义。如上文x[11]到x[100]没有意义。

    若形参数组长度小于实参数组,可能导致部分实参数组未被操作。

    但无论长度如何,关键都在于对形参数组操作的边界设置是否合理,如下文的代码并无问题。

    void invert(int x[10]){
    	//函数部分 
    	for(register int i=1;i<=100;i++){
    		x[i]=0;
    	} 
    }
    int main(){
    	int a[100];
    	invert(a);
    	//主函数调用部分 
    }
    

    2.对于多维数组:
    在函数定义时对形参数组可以指定每一维的长度,也可省去第一维的长度。因此,以下写法都是合法的:

    void invert(int sum[][110])
    
    void invert(int sum[110][110])
    
    展开全文
  • 函数调用

    千次阅读 2018-11-16 11:54:08
    函数调用 子函数 定义:能被其他程序调用,在实现某种功能后能自动返回到调用程序去的程序。其最后一条指令一定是返回指令,故能保证重新返回到调用它的程序中去。也调用其他子程序,甚至自身调用(如递归...
      						子函数调用
    
    1. 子函数
      定义:能被其他程序调用,在实现某种功能后能自动返回到调用程序去的程序。其最后一条指令一定是返回指令,故能保证重新返回到调用它的程序中去。也可调用其他子程序,甚至可自身调用(如递归)。
    2. 函数的调用形式
      函数调用的一般格式为:(在main函数中)
      <函数名> ([<实际参数列表>]);
    3. 函数声明
      函数声明的一般格式:
      <返回类型><函数名> ([<形参类型1>][<形参1>],[<形参类型2>][<形参2>]…);
      例:
    #include<stdio.h>
    
    int main()
    {
        void putin(int);    //函数原型声明
        int number;
        printf("请输入数字:\n");
        scanf("%d",&number);
        putin(number);     //调用子函数putin()
        return 0;
    }
    
    void putin(int number)
    {
        printf("%c\n",'number');  //将输入的数的ascll码输出
        return ;
    }
    

    运行结果:

    注:
    个人自己的理解:

    1.在函数声明的时候,个人比较喜欢放到头文件的下面。声明时不是按照函数原型声明(省略形参),而是详细的都列出来,因为在用函数原型声明的时候很容易出错,倒不如直接全部声明。

    2.在函数调用的时候倒是没有什么不一样的,基本上就是这个模板.

    最后在给一个你让我看的例子;

    法一:

    #include<stdio.h>
    //声明子函数
    void name(char student_name[20]);
    void place(char student_hometown[20]);
    
    int main()
    {
        char student_name[20];
        char student_hometown[20]; //定义两个字符变量
        //调用子函数
        name(student_name);
        place(student_hometown);
        //界面化实现
        printf("*******************************\n");
        printf("Welcome!  %s \n",student_name);
        printf("come from:%s!\n",student_hometown);
        printf("*******************************\n");
        return 0;
    }
    
    //name子函数
    void name(char student_name[20])
    {
        printf("Enter your name:\n");
        scanf("%s",student_name);
        return ;  //纯属个人习惯,没有也是对的
    }
    //place子函数
    void place(char student_hometown[20])
    {
        printf("Enter your hometown:\n");
        scanf("%s",student_hometown);
        return ;
    }
    

    法二:

    #include<stdio.h>
    //声明子函数
    /*
    void name(char student_name[20]);
    void place(char student_hometown[20]);
    */
    //name子函数
    void name(char student_name[20])
    {
        printf("Enter your name:\n");
        scanf("%s",student_name);
        return ;  //纯属个人习惯,没有也是对的
    }
    //place子函数
    void place(char student_hometown[20])
    {
        printf("Enter your hometown:\n");
        scanf("%s",student_hometown);
        return ;
    }
    
    
    int main()
    {
        char student_name[20];
        char student_hometown[20]; //定义两个字符变量
        //调用子函数
        name(student_name);
        place(student_hometown);
        //界面化实现
        printf("*******************************\n");
        printf("Welcome!  %s \n",student_name);
        printf("come from:%s!\n",student_hometown);
        printf("*******************************\n");
        return 0;
    }
    
    

    注:其实法二,并不算是一种方法。只是把所有的子函数放在了main函数的上边就不需要声明了。
    遇到的一些问题:
    1.尽量不要在声明的时候省略形参,其实这个我试了一下,报错了,也没调出来。
    2.注意一下关于字符串的处理,值得深入研究字符串。
    3.注释打一下,既是练打字,还能让自己更了解自己的代码,主要是能让别人读懂。

    省略形参情况:

    所以以后尽量不要使用省略形参的情况!

    展开全文
  • 汇编:函数调用

    千次阅读 2019-07-18 18:57:33
    让我们再回忆一下脑海中关于函数调用的概念,也许会是这个样子: 这里的“控制流转移”又是如何发生的呢?在解释这个之前,也许我们需要科普一点有关于汇编的知识。 2. 函数调用中的一些细节说明 2.1 函数调用中的...
  • 函数的可重入和不可重入

    千次阅读 2017-04-15 18:26:26
    https://www.ibm.com/developerworks/cn/linux/l-reent.html这是一篇描述重入函数不可重入函数的文章。先把他copy过来: 在早期的编程中,不可重入性对程序员并不构成威胁;函数不会有并发访问,也没有中断。在很...
  • 上期在说到Python实现阶乘相加对于函数的调用及递归没有进行详解,这次主要介绍清楚C语言中的函数调用。 在C语言中,不管是对数值进行交换,或者是对数组进行排序,考虑其时间复杂度,我们都喜欢创建一个调用...
  • 静态函数调用

    千次阅读 2020-01-09 15:48:09
    静态函数 #include <iostream.h> class Point { public: void output()//非静态成员函数 ...调用1:非静态成员函数和非静态成员属于对象的方法和数据,也就是先产生类的对象,然后通过类的对象去引用。 voi...
  • C语言函数调用栈(一)

    万次阅读 多人点赞 2018-07-19 22:16:25
    程序的执行过程看作连续的函数调用。当一个函数执行完毕,程序要回到调用指令的下一条指令(紧接call指令)处继续执行。函数调用过程通常使用堆栈实现,每个用户态进程对应一个调用栈结构(call stack)。编译器使用...
  • 一、Java 中函数参数是接口类型、 二、函数参数是接口类型 可以 直接传递闭包、 三、完整代码示例、
  • windows环境下C++代码打印函数堆栈调用情况

    千次阅读 多人点赞 2019-09-04 15:38:39
    函数之间的是会相互调用的,在某一时刻函数之间的调用关系,可以通过函数调用堆栈表现出来,这个调用堆栈所展现的就是函数A调用了函数B,而函数B又调用了函数C,这些调用关系在代码中都是静态的,需要程序运行就...
  • } 3、拷贝构造函数的调用时机   C++中拷贝构造函数调用时机通常有三种情况: 使用一个已经创建完毕的对象来初始化一个新对象 值传递的方式给函数参数传值 以值方式返回局部对象 class Person { public: Person()...
  • C语言之可重入函数不可重入函数

    千次阅读 2017-09-06 21:51:32
    那么不同任务调用这个函数时可能修改其他任 务调用这个函数的数据,从而导致不可预料的后果。 那么什么是可重入函数呢?所谓可重入是指一个可以被多个任务调用的过程,任务在调用时不必担心数据是否会 出错。 不可...
  • c语言函数调用及应用举例

    万次阅读 多人点赞 2019-04-20 16:27:29
    一般来说,执行源程序就是执行主函数main,其他函数只能被主函数所调用,而其他函数之间也可以相互调用。 1.标准库函数: 分为:I/O函数,字符串,字符处理函数,数学函数,接口函数,时间转换和操作函数,动态...
  • C++中函数调用时的三种参数传递方式详解

    万次阅读 多人点赞 2017-08-31 20:44:51
    如果以引用为参数,则既可以使得对形参的任何操作都能改变相应的数据,又使得函数调用显得方便、自然。引用传递方式是在函数定义在形参前面加上引用运算符“&”。 #include using namespace std; void ...
  • (struct)结构体变量作为函数参数调用的方法小结

    万次阅读 多人点赞 2015-04-29 19:37:38
    结构体变量作为函数参数传递的3种方法 将一个结构体变量中的数据传递给另一个函数,有下列3种方法: 用结构体变量名作参数。一般较少用这种方法。 用指向结构体变量的指针作实参,将结构体变量的地址传给形参。 用...
  • 3.C++函数调用过程

    万次阅读 2020-03-08 17:31:05
    函数调用堆栈的过程 1.函数中普通变量的内存分配问题 当一个函数进行调用,函数的形参、以及函数的局部变量都会在栈中被分配内存,而栈又分两种; 栈低不变,栈顶不断动态变化; 栈顶不变,栈低在动态变化; #...
  • 自定义函数调用自定义函数 在我们编写C语言程序,可以将要经常用到的或者有自己单独作用的那一部分代码独立成一个函数,不仅可以简化我们的程序,还可以使我们的程序更加可见话。
  • 函数调用形式为函数名 (实参表列)。C语言可以嵌套调用函数。在调用函数又调用该函数本身为递归,必须有退出条件。数组元素相当于普通变量,数组名作参数要求形参和实参必须为类型相同的数组。局部变量只在本函数...
  • 二维数组作为函数的参数进行传值,调用和使用

    千次阅读 多人点赞 2019-09-06 16:00:26
    一、 情况1:实参为二维数组 在main函数中 int a[3][3]; 调用形式 print(a);...当调用形式为 print( (int **) a),这种定义,对应int a[3][3]没有问题OK; void print(int* a[3]); //ERROR;这...
  • UE4 C++利用函数调用UFUNCTION函数

    千次阅读 2020-05-07 16:03:36
    对于纯蓝图定义的函数可以使用函数 UObject中的 virtual void ProcessEvent( UFunction* Function, void* Parameters ) 进行调用 比如蓝图终定义了BP_Func() 在C++代码中这样调用: ProcessEvent...
  • 在Linux应用程序中打印函数调用

    千次阅读 2019-03-08 11:10:58
    在Linux中打印函数调用栈 要求 在Linux系统的应用程序中写一个函数print_stackframe(),用于获取当前位置的函数调用栈信息 方法 execinfo.h库下的函数backtrace可以得到当前线程的函数调用栈指针和调用栈深度,...
  • C语言 函数参数和调用函数

    千次阅读 多人点赞 2019-04-14 08:39:07
    调用函数时,有两种向函数传递参数的方式: 传值调用 默认情况下,C 语言使用传值调用方法来传递参数。一般来说,这意味着函数内的代码不会改变用于调用函数的实际参数。函数 swap() 定义如下: /* 函数定义 */ ...
  • 函数的参数和函数调用

    千次阅读 2015-03-14 16:07:06
    在定义函数时函数名后面括号中的变量称为“形参”,在主调函数(一般为Main)调用一个函数时函数名后面括号中的参数(可以是一个表达式)称为“实参”。 例如: void func(int x,int y) { ........
  • 函数指针的两种调用方式

    千次阅读 多人点赞 2020-05-16 20:35:09
    void test(int); int main(void){ void (*fp)(int); fp=test; (*fp)(9); fp(9); return 0; } void test(int a) { printf( "%d\n", a ); } 这两种形式是等价的,都是为ANSI C所接受的。 历史上,贝尔实验室...
  • c#的构造函数及构造函数调用

    万次阅读 2015-12-01 16:53:07
    C#构造函数的特性一、 什么是C#构造函数?Construct,Function  C#构造函数是一种特殊的成员函数,它主要用于为对象分配存储空间... (2)C#构造函数没有返回类型,它可以带参数,也可以带参数;  (3)声明类对象
  • 除了《静态分析C语言生成函数调用关系的利器——calltree》一文中介绍的calltree,我们还可以借助cflow辅助我们阅读理解代码。(转载请指明出于breaksoftware的csdn博客)cflow的说明和安装 cflow是一款静态分析...
  • 再谈C语言有参函数调用时参数值传递问题 分类: C/C++ 2012-04-24 16:51 1637人阅读 评论(0) 收藏 举报 C语言值传递参数传递指针长春工程学院csdn俱乐部 C语言有参函数调用时参数间数据传递问题 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 945,055
精华内容 378,022
热门标签
关键字:

对于void函数调用时不可作为