C语言【函数、作用域、常用系统函数】
C语言【函数、作用域、常用系统函数】
一、函数
1、函数的声明
// 函数声明格式
int add(int x, int y);
// 或
int add(int, int);
自定义函数如果放在main函数之后,需要声明函数才可以访问到。如果未声明,则编译器会自动补一个返回类型未int类型的声明,这样以来,如果自定义函数返回值不为int,会报错。
结论:记得加函数声明。
2、函数的传值和传址。 todo
3、函数的名称即代表函数的地址。
4、C语言不支持函数的嵌套声明和定义。
5、形参和实参的区分:调用其他函数时,传递的参数叫实参。形参和实参数量要一致。
6、函数中声明了返回值类型,但没写return:如果函数只有一个参数,且实参传的变量,gcc返回为此参数值(试了三次,变量为整型),其他情况返回的值挺随机的。
7、gcc允许其他函数调用main函数,警告但不报错。
8、程序启动时,操作系统开启main函数线程;main函数执行完毕后,将返回值(代表正确与否的状态)返回给操作系统;main函数的参数由操纵系统提供,一般为:int argc 表示main函数的参数个数,char const * argv[]表示具体的参数,可以通过gcc编译时指定这些参数。
补
1、如果使用vscode进行多文件编译,需要修改配置;使用gcc命令进行多文件编译时,只需加上要编译的文件即可。
2、分文件编译时,想要调用其他文件的函数,需要声明该函数,尽量别让编译器隐式声明那个只有int类型的。
3、分文件编译时,想使用其他文件的全局变量,需要用extern声明后使用,不加extern视为重新定义了一个,这种情况这个重新定义的不报错,只不过不建议——想使用其他文件的就extern,不想使用就别用这个名,尽量不要模棱两可。
二、作用域
1、作用域分为全局作用域、局部作用域、块作用域。
2、同一作用域内不能有同名标识符。可以在小作用域定义与大作用域同名的标识符。作用域大的标识符管的范围大,作用域小的标识符优先级高。
3、全局作用域。
定义在所有函数和代码块之外,值存储在全局静态区,初始值默认为0或"",声明周期贯穿整个程序。
static:静态全局变量或函数等在其他文件内不可见,使用extern声明也不行,这就是静态全局变量的作用。
4、局部作用域。
定义在函数内(参数也算函数内),值存储在栈空间,初始值为随机值(例外的情况往下看)。
static:局部变量如果加了static,表示为静态局部变量。 静态局部变量存储在全局静态区,和全局变量在一个区域,它默认值0或"",保留之前的值直到修改或者程序执行结束(static赋初值那个代码只第一次调用它的函数时执行,之后不再执行。)。虽然它和普通局部作用域不在同一区域,但同一局部作用域内仍不能存在同名的静态和普通局部变。
5、块作用域。 C99标准。
一个代码块内,比如 if 或 for 或 就一个{}
6、如果小作用域有和大作用域同名的变量,如何使用大作用域的变量?
块作用域与局部作用域有同名的,似乎没法使用局部的。
局部与全局有同名的变量时,可以定义一个代码块,在代码块中使用extern声明全局变量并使用,这个变量就是那个全局的变量。如果不在代码块中声明会报错。
如果全局变量中没有你在局部变量用extern声明的变量,则局部变量中用extern声明的这个变量只能声明不能赋初值或使用。
补
递归。找好递推公式和递归结束条件。递推公式要求:f(n)内每个包含变量的小公式都可以用f(n)中n的变化来表示。
三、常用系统函数
1、 <string.h> 库中的常用函数。
strlen(str); //返回str长度,类型为size_t。 重点:好处为自动减掉了'\0'那个长度。
strcpy(str1, str2); // 将str2的值复制给str1。 重点:对于数组,str2>str1时会溢出,给警告,不报错。
strcat(str1, str2); // 将str2的值拼接到str1之后。重点:str1长度小于拼接后的值时,会溢出,给警告,不报错。
2、<stdio.h> 库中常用函数。
// sprintf(...)
char arr[100] = {'a'};
int a=1, b=2, c=3;
sprintf(arr, "第%d,第%d,第%d", a, b, c); // 用来按格式组合字符串的
printf("%s\n", arr); // 第1,第2,第3
// sscanf(...)
char s[] = "树上有44颗红柿子,树下有66座石狮子。";
int x, y;
sscanf(s, "树上有%d颗红柿子,树下有%d座石狮子。", &x, &y); // 拆数的。想一想拆字符串怎么整
printf("%d %d\n", x, y); // 44 66
3、<time.h> 库中常用函数。
time(&变量名); // 将时间戳(1970年1月1日到现在的秒数)赋给这个变量,该变量需要时 time_t 类型
time(NULL); //返回时间戳,这个是返回,上面的是赋值给参数。
// 以上两种结合起来,既赋值参数又返回。也就是第一种就可以返回时间戳。
ctime(&时间戳变量); // 返回。返回可视化的字符串。
/*-------以下是一个ctime函数的示例-------*/
time_t ti = time(NULL);
// char st[100] = ctime(&ti); // 不成立,会报错,返回的指针,不能赋给数组,但可以指针接收或者直接输出。
printf("%s\n", ctime(&ti)); // Tue Nov 21 20:27:40 2023
/*-----------上面示例结束---------*/
difftime(时间戳1, 时间戳2); // 返回差值,返回类型double。 参数不加&
4、<math.h> 库中常用函数。
// 以下函数都为返回,不改变原参数
sqrt(x); // 平方根
cbrt(x); // 立方根
pow(x, y); // x的y次方
fabs(x); // 绝对值
ceil(x); // 向上取整,比原数大
floor(x); // 向下取整,比原数小
round(x); // 四舍五入取整。round(-12.51)返回-13
trunc(x); // 截断小数