【C语言】定义了一个有参数的函数,调用时却不带参,为何不报错?

【C语言】定义了一个有参数的函数,调用时却不带参,为何不报错?,第1张

如果定义的时候是有参的, 调用的时候无参, 可编译过,

只能说明在调用文件中没有声明或者声明错误

这时会有不可预知的结果

另外一种可能出现这种不同地方调用参数情况不同的,就是声明的是可变参数

#include <windowsh>

BOOL CreateProcess

(

LPCTSTRlpApplicationName,

LPTSTRlpCommandLine,

LPSECURITY_ATTRIBUTES lpProcessAttributes。

LPSECURITY_ATTRIBUTES lpThreadAttributes,

BOOL bInheritHandles,

DWORD dwCreationFlags,

LPVOID lpEnvironment,

LPCTSTR lpCurrentDirectory,

LPSTARTUPINFO lpStartupInfo,

LPPROCESS_INFORMATION lpProcessInformation

);

详见

位于全局区的变量叫做全局变量,位于函数中的变量叫做局部变量。

全局变量有默认值0,局部变量没有默认值,使用前必须初始化。

int a, b; //全局变量a和b,有默认值0

int main()

{

int a; //局部变量a,没有默认值

a = a+1; //错误,没有初始化a就使用了a的值

}

  C语言具有简洁紧凑,灵活方便,运算符丰富,数据类型丰富,表达方式灵活实用等特点,所以C语言程序设计更主动、灵活。很多人从C语言入门编程,下面整理了一些C语言基础知识,希望对大家有所帮助!

 1C语言中,变量必须先声明后使用,即一个程序块(花括号对)中所有临时变量必须在第一条可执行语句之前全部声明,而不能像C++那样随用随声明;

 2C语言中参数传值传递形参,即为参数的拷贝,此与C++/JAVA相同,同时值得注意,ANSI C不支持引用,此与C++/JAVA有区别,那么要对参数进行修改只能使用指针方式(指针传值指针本身仍是形参,要修改指针本身那必须使用双重指针);

 3C语言默认类型为int,即参数无类型或函数无返回值类型声明,则认为是int(貌似一些编译器不支持),同时不建议使用该特性;

 4无参数的函数声明应当使用void表明,否则C语言按照老式声明方法忽略参数类型检查;

 5全局变量建议全大写,局部变量建议全小写,内部变量31个字符有效,外部变量不区分大小写,仅6个字符有效,所以必须保持唯一性;

 6ANSI C是按照多字节实现的,UNICODE是后来发展的,所以有char/WCHAR,与NET中char直接是双字节有区别,在C#中导入dll时值得注意;

 7C语言支持枚举,并且枚举和int直接强制类型转换即可,比NET方便;

 8#define声明宏定义直接在编译时替换,不进行类型检查,const声明常量则可以进行类型检查;

 9运算符的优先级记忆比较麻烦,还是()可靠;

 10goto并不是一无是处,在不考虑程序可读性的情况下可能获得更高的效率;

 11函数实际也可以与特殊的类型相对应,那样对于理解函数指针比较方便,函数为外部类型;

 12static用于全局变量和函数则限定该变量和函数的使用范围仅为该源文件(从而无需考虑与其他源文件不得重名),用于函数内部变量则该变量的内存分配和回收不再同于普通临时变量(调用函数生成,函数返回销毁),而是一直存在于静态变量区,从而可以保存一些状态;

 13头文件的作用体现在调用其他源文件时不需要再次写函数定义,所以实现函数是不需要头文件的,调用时才需要,可以采用富头文件定义一大组接口,然后使用多个源文件分别实现;

 14寄存器变量使用register声明,仅适用于使用频率高的局部变量(含形参)(受限于底层硬件,不一定会被分配到寄存器,但是这么写不影响效率);

 15全局变量和静态变量默认初始化为全零且仅初始化一次,局部变量默认初始化为未定义且每次都会重新初始化;

 16递归调用的方法一般比较紧凑,但是每次调用会单独维护调用的`堆栈,所以效率不是最高;

 17#include的作用体现于将一些内容避免重新写一遍(主要是类型、函数和外部变量定义),所以实际上不一定为h文件;

 18表示一行尚未结束,对于定义长的字符串和define比较有用;

 19函数调用的执行顺序不确定,所以对于a()+b()这样函数中使用相同变量并且改变其值的需要借助临时变量处理,防止不同实现的调用顺序不一致;

 20##用于宏定义中连接前后两个部分,如cat(a, b) a ## b;

 21指针是C/C++的重要内容,当然也是双面刃,用好了很方便而且高效,用不好那就造成程序不稳定;

 22使用va_list, va_start, va_arg, va_end来定义可变参数的函数,通过va_start函数中的第一个不变参数将va_list指向参数列表(函数调用的栈中),然后通过va_arg获取每个参数并将va_list移动指定类型的长度,最后则通过va_end完成必要的回收工作,需要指出的是va_arg没有结束边界,所以比较有效的方式有两种,一种对于参数类型一致,则可以第一个参数指出后续参数的总数,然后依次获取,另一种对于不同类型的参数混用,则可以通过类型标识+参数配对的方式进行使用(第一个参数依然可以指定数量,当然也可以检查标识),从而避免最后读取无效的参数,对于可变参数仅支持int和double两种类型(参数未限定类型,故按照旧式声明理解)以及指针类型;

 23函数指针是用来在C语言中实现动态调用的比较有效的方式

 24结构体用作参数依然是拷贝为形参传递,这点与JAVA中全部对象都是类有区别(类的对象通过引用传值,C#支持struct),所以对于大的结构体事宜使用指针传递,而对于小的结构体拷贝传值效率并不低;

 25代码中字符数组为静态常量,对其 *** 作无效,程序块中数组的声明是可以自动回收的,通过malloc/calloc分配的内存为堆内存,需要自行通过free回收;

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/12176214.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-21
下一篇2023-05-21

发表评论

登录后才能评论

评论列表(0条)

    保存