首页 > 其他分享 >C语言 笔记4

C语言 笔记4

时间:2023-08-20 16:35:37浏览次数:40  
标签:__ 头文件 函数 int 笔记 C语言 var 全局变量

全局变量

  • 定义在函数外部的变量是全局变量。
  • 全局变量具有全局的生存期和作用域
    • 全局变量与任何函数都无关
    • 在任何函数内部都可以使用全局变量
  • 不能使用变量给全局变量初始化
  • 不初始化的全局变量默认为NULL
  • 函数内的同名变量会隐藏全局变量
int a = 1;
{
	int a = 2;
	{
		int a = 3; 
		printf("%d\n",a);
	}
}

output: 3;

静态本地变量

  • 使用static修饰一个变量变量使其变成静态本地变量

  • 静态本地变量可以理解为特殊的全局变量(生存期相同,内存区域相同,作用域不同)

  • 静态本地变量具有全局生存期,但作用域为局部作用域

    • static的意思是局部作用域(本地可访问)

eg:

#include<stdio.h>

int f(void);

int main(){
    f();
    f();
    return 0;
}

int f(void){
    int var = 1;
    static int static_var = 1;
    var++;
    static_var++;
    printf("var => %d\nstatic_var => %d\n",var,static_var);
}

output:

var => 2
static_var => 2
var => 2
static_var => 3

返回指针的函数

  • 返回函数内本地变量的指针是危险的,离开此函数后,谁也无法保证这片内存空间会不会分配给别人。

  • 返回全局或者静态本地变量是安全的,他们和函数无关。

  • 返回在函数内malloc的内存是安全的,但是容易出问题,不推荐。

  • 返回传入函数的指针是安全的。


尽量避免使用全局变量

宏定义

#define

  • 开头的是编译预处理指令

  • 他们不是C语言的成分,但是C语言程序离不开他们
  • define用来定义一个宏

#define  标识符  值
// 注意,后面没有分号(他不是C语言的语句)
  • 标识符必须是一个单词,值是什么都可以

写了define后,预编译所执行的操作是简单的“文本”替换。把代码中所有出现标识符的地方替换为后面的值,可以使用能够 gcc --save-temps 来查看预编译后产生的文件,来查看这件事。

  • 后面的宏中如果出现前面宏中定义的标识符,也会被替换
  • 宏需要写在一行,如果需要多行书写,可以在行尾加 \(不只是宏可以这样,C语言代码也可以)
  • 宏也可以写注释,不会被当作宏的一部分
  • 没有值的宏可以用作条件编译,后面可以使用其他预处理质量来检测这个宏是否定义过。(如 #define _DEBUG

预定义的宏

这些宏默认提供的,可以实现一些功能

用处
__LINE__ 当前行号
__FILE__ 当前文件名
__DATE__ 编译日期
__TIME__ 编译时间
__FUNC__ 当前所在的函数名
__STDC__ __STDC__是预定义宏。当它被定义后,编译器将按照ansic标准来编译你的c程序。

多个源代码文件

在设计大程序时,不可能将所有的代码都写在 main.c 中,一般将一个程序拆分成多个 .c 文件.可以使用下面命令将多个 .c 文件编译成一个可执行程序:

gcc main.c [xxx.c yyy.c zzz.c] [-o] [output]

如果使用ide集成开发环境,一般会有项目,编译时会将项目中的 .c 文件编译成一个可执行程序.

头文件

头文件

我们将多个 .c 文件编译成一个可执行程序时.并不是将其他.c文件插入到 main.c 的某一个部位.所以 main.c 在使用其他 .c 文件中的函数时,需要在开头声明一下函数原型.

如果不声明函数原型,但是你对函数参数的传入和结果的传出使用正确的话,也不会出现问题.但是一旦使用错误,就会出现问题.

此时就需要用到头文件了,头文件的后缀为 .h .我们可以使用 #include 来插入一个头文件.

#include <stdlib.h>
#include "node.h"
  • <> 引入头文件,会在系统特定的目录找这个头文件.一般用于引入标准库的头文件.
  • "" 引入头文件,会先在当前目录寻找这个头文件,找不到时再去系统特定目录寻找,一般用于引入自己写的头文件.

头文件中一般包含了这些函数的函数原型(并不包含函数本身,如果你想也可以,但一般不这么做).在编译预处理时,编译器会把头文件插入在引入头文件的位置.这样就不用在 main.c 中声明函数原型了.

关于#include的一个误区

  • #include 不是用来引入函数库的

  • stdio.h 里只有 printf 的函数原型, printf 的函数写在别的地方

  • C语言编译器会默认引入所有的标准库

  • #include<stdio.h> 只是为了让编译器知道 printf 的函数原型,确保在调用时给出的参数值是正确的类型

在学这节之前,我也一直认为 #include 是引入一个函数库o(╥﹏╥)o

局部函数

如果希望一个 .c 文件中的某一个函数,只能在该 .c 中使用. 需要在函数定义的开头加 static 来修饰. 此时这个函数可以看做一个局部函数,只在他所在的 .c 文件中生效.

声明

声明有很多种, 可以使用 extern 来声明一个变量.

int i; // 变量的定义
extern int i; // 变量的声明

这个关系有点像函数的定义和函数原型的声明. 同样,如果想在 main.c 中使用一个其他 .c 文件的全局变量,就需要声明一下.

  • 声明不会产生代码.

  • 定义会产生代码.

头文件

  • 只有声明可以写在头文件中.这是一个约定俗成的规矩,并不强制.
  • 如果在头文件中写定义,可能会导致同一实体被重复定义.或者出现同名的定义.
    • 某些编译器允许多个编译单元中有同名函数的存在,或者用 weak 修饰符强调这种存在.

重复声明

  • 同一个编译单元中,同名的结构不能被重复声明.
  • 如果头文件中声明了一个结构,这个结构很可能会被重复声明导致程序出错.
  • 我们可以用 "标准头文件结构" 来避免这种情况发生.

标准头文件结构:

/*
	如果这个头文件被引用过一次,___XXX___就会被定义,下一次重复引用时,直接跳到#endif,中间的代码就不会被引用了.
*/
#ifndef __XXX__ // 如果没有定义__XXX___
#define __XXX__ // 定义___XXX___
..CODE..
#endif

这样就可以保证一个头文件只会被引用一次..

标签:__,头文件,函数,int,笔记,C语言,var,全局变量
From: https://www.cnblogs.com/orzmiku/p/17644191.html

相关文章

  • C语言 笔记3
    可变数组设计一个Array库,提供数组初始化,数组数据查看和修改的功能,且数组大小可变。array.h/*可变数组*///array_block,每次触发自动增长时增长的数量,记作一个array_block#defineARRAY_BLOCK10typedefstruct{intsize;int*array;}Array;Arrayarr......
  • C语言 笔记5
    格式化输入输出输入-printfprintf("%[flags][width][.prec][hlL]type...",参数表...);返回值输出的字符数flagFlag含义-左对齐+给一个正数强制加一个+号(space)正数留空0左边补零,不能和左对齐同时使用width和precwidth含义number......
  • 「Python」第一阶段第七章笔记
    函数的多返回值"""函数的多返回值"""defmy_return():return1,2x,y=my_return()print(x,y,type(x),type(y))函数的多种传参方式"""函数的多种传参方式-位置-参数-缺省-不定长"""#位置传参形参实参位置对应defadd(a=0,b=0)......
  • 「Python」第一阶段第五章笔记
    函数的初体验"""函数的初体验"""name="OrzMiku"print(f"{name}这个名字有{len(name)}个字符长")函数的定义"""函数的定义def函数名(参数表):函数体return返回值"""defsayHello():print("HelloW......
  • 「Python」第一阶段第二章 笔记
    字面量#字面量:写在程序中固定的值print(114514)print(1919810)print("HelloWorld")注释"""Python中的多行注释"""print("多行注释用三个引号开头三个引号结尾")#Python中的单行注释print("单行注释以井号开头")变量"""变量名=变量值&......
  • 「Python」第一阶段第三章笔记
    布尔类型和比较运算符"""跳过"""if语句基本格式"""if语句基本格式if条件:代码块"""age=int(input("请输入你的年龄:"))ifage>=18:print("老东西速速爆金币!")quit()print("小东西给我磕一个!")......
  • 「Python」第一阶段第四章笔记
    while循环"""while条件:代码块"""num=255;#python没有++和--whilenum:print(num)num-=1for循环for基础语法"""for循环(感觉更像是一个foreach循环)for临时变量in序列类型:代码块"""name="OrzMiku......
  • 「Python」第二阶段第一章笔记
    初识对象"""初识对象"""#1.设计一个类classStu:name=None#学生姓名gender=None#学生性别nationality=None#学生国籍native_place=None#学生籍贯age=None#学生年龄#2.创建一个对象stu_1=Stu()#3.对象属性进行赋......
  • 计算机萌新的成长历程——初识C语言2
    今天我将分享初识数据类型的学习体会和心得。刚刚开始接触数据类型,我学习到了以下几个数据类型char——字符数据类型short——短整型int——整型long——长整型longlong——更长的整型float——单精度浮点数double——双精度浮点数下面我将分享一下我对这些数据类型的理解。理解这......
  • Linux笔记(银河麒麟V10)
    Linux下切换Python版本$whereispython$rm/usr/bin/python$ln-s/usr/bin/python3.6/usr/bin/python测试:$python--versionPython3.8.2安装Node.js-v18$curlhttps://nodejs.org/dist/v18.17.0/node-v18.17.0-linux-x64.tar.xz--outputnodejs18.tar.xz#......