C语言学习

一、基础认识

程序总是从main函数开始执⾏
程序中要求计算机的操作是由函数中的C语句完成的
在每个数据声明和语句的最后必须要有⼀个分号

  • 预处理指令:由以"#"开头的特殊语句组成。预处理指令不 是真正的C语句,⽽是⽤来指导编译器在编译之前进⾏⼀些处理操作的。
cpp 复制代码
#include:⽤于引⼊头⽂件,将头⽂件的内容插⼊到当前位置。
#define:⽤于定义宏,将标识符替换为指定的值或代码⽚段
  • 全局声明:是指在函数外部声明的变量或函数,其作⽤域在整个程序中都可⻅。全局声明可以在任何 函数中使⽤,⽽不需要在每个函数中重新声明。

  • 函数定义:是指在程序中实现函数的具体功能。函数定义包括函数的返回类型、函数名、参数列表和 函数体。

cpp 复制代码
返回类型 函数名(参数列表) {
 // 函数体
 // 执⾏具体的功能
 // 可能包含⼀条或多条语句
}

二、顺序程序设计

1、常量:

在程序运⾏的过程中,其值不能被改变的量称为常量

  • 整型常量 eg:1000、0、123.25、-652...

  • 实型常量 :⼗进制⼩数形式、有数字和⼩数组成、指数形式。

  • 字符常量 :普通字符。⽤单引号括起来的单个字符。 eg:'5'、'e'、'?'....

  • 转义字符:以 \ 开头的字符

    • 字符串常量:双引号括起来的若⼲个字符。eg:"hello"、"123"
      符号常量:⽤ #define 指令,指定⽤⼀个符号名称代表⼀个常量。
    cpp 复制代码
    #define PI 3.1415 //末尾没有分号,程序⽤到 PI 就代表是3.1415

2、变量:

在程序运⾏期间,其值可以改变的量叫做变量。变量在使⽤前需要先声明,声明变量时
需要指定变量的类型和名称。

3、常变量(在定义变量前加⼀个 const ):

表示该变量是常量,其值不能被修改。常变量⼀旦被初始化,其值将在整个程序执⾏过程中保持不
变。

4、数据类型

(1)、整型数据

**1.**基本整型(int 型)

占⽤4个字节,取值范围为-2,147,483,648到2,147,483,647或0到4,294,967,295

**2.**短整型 (short int型)

占⽤2个字节,取值范围为-32,768到32,767或0到65,535

3.⻓整型 (long int 型)

占⽤4个字节(32位系统)或8个字节(64位系统),取值范围为-2,147,483,648到 2,147,483,647

**4.**双⻓整型 (long long int 型)
占⽤8个字节,取值范围为-9,223,372,036,854,775,808到9,223,372,036,854,775,807

(1-1)整型变量的符号属性

C语⾔中的整型变量可以具有符号属性(有符号)或⽆符号属性(⽆符号),这取决于变量的声明 ⽅式。

有符号整型变量可以表示正数、负数和零,⽽⽆符号整型变量只能表示⾮负数(包括零)。
如果不明确指定符号属性,默认情况下,int和unsigned int被视为有符号和⽆符号整型变量。
unsigned short类型:

**(2)**字符型数据

字符变量就是⽤类型符 char 定义字符变量。
有符号字符型(signed char,⼀般写作 char )字节数: 通常为1个字节(8位),取值范围:-128 到 127。
⽆符号字符型(unsigned char): 字节数:通常为1个字节(8位),取值范围:0 到 255。
**(3)**浮点型数据

  • 单精度浮点型(float 型)
    • 通常占⽤4个字节(32位),其有效数字位数为约6-9位。该类型可以表示⼤约1.2e-38到
      3.4e+38之间的数值。
  • 双精度浮点型(double 型)
    • 通常占⽤8个字节(64位),其有效数字位数为约15-18位。该类型可以表示⼤约2.3e-
      308到1.7e+308之间的数值。
  • ⻓双精度型 (long double 型)
    • 占⽤的字节数较为可变,通常是8个字节或更多。其有效数字位数也会相应增加。这种类
      型通常提供⽐double更⾼的精度

5、运算符

5.1基本算术运算符

  • 加法运算符(+):将两个操作数相加。
  • 减法运算符(-):从第⼀个操作数中减去第⼆个操作数。
  • 乘法运算符(*):将两个操作数相乘。
  • 除法运算符(/):将第⼀个操作数除以第⼆个操作数,得到商。
  • 取模运算符(%):将第⼀个操作数除以第⼆个操作数,得到余数。
  • 正号运算符(+):表达数据为正
  • 负号运算符(-):表达数据位负

5.2⾃增⾃减运算符

1.⾃增运算符有两种形式:前缀形式和后缀形式。

前缀形式的⾃增运算符(++x)会先将操作数的值增加1,然后返回增加后的值。

后缀形式的⾃增运算符(x++)会先返回操作数的值,然后再将其增加1。

2.⾃减运算符的使⽤⽅法与⾃增运算符类似,只是将值减少1。

5.3、算术表达式

加法(+)、减法(-)、乘法(*)、除法(/)和取模(%)等。

5.4不同数据类型之间的混合运算

5.4.1整数和浮点数的混合运算:

如果⼀个操作数是浮点数,那么另⼀个操作数将被⾃动转换为浮点数,结果将是浮点数。

如果⼀个操作数是整数,⽽另⼀个操作数是浮点数,那么整数将被⾃动转换为浮点数,结果将是浮点数。

cpp 复制代码
int a=5;

float b= 2.5;

double c;

C=a+b;//

整数a被自动转换为浮点数,结果c为浮点数

C=a*b;//整数a被自动转换为浮点数,结果c为浮点数
5.4.2字符和整数的混合运算

字符可以被视为整数类型,因此可以与整数进⾏运算。
字符与整数之间的运算结果将是整数。

cpp 复制代码
char ch = 'A';
int num = 2;
int result;
result = ch + num; // 字符ch被视为整数类型,结果result为整数
5.4.3不同整数类型的混合运算

如果两个操作数的类型不同,那么C语⾔会将它们转换为相同的类型,然后进⾏运算

转换的规则是,将较⼩的整数类型转换为较⼤的整数类型。

long long > long > int > short > char
需要注意的是,混合运算可能会导致数据丢失或精度损失。因此,在进⾏混合运算时,应该确保转
换是安全和合理的,以避免出现错误。

5.5 强制类型转换运算符

它的语法形式是在要转换的值或表达式前⾯加上括号,并在括号内指定要转换的⽬标类型。

cpp 复制代码
(type) expression
//其中, type 表示⽬标类型, expression 表示要转换的值或表达式。
/强制类型转换只是转换当前的临时值,但该表达式结束后,数据仍为原类型。
在char ch = (char) a; 过后,a 还是int整型 *** 

5.6 赋值语句

  1. 赋值运算符(=):将⼀个数据赋值给⼀个变量
  2. 复合赋值运算符
  • +=:加法赋值运算符

将右操作数的值加到左操作数上,并将结果赋给左操作数。

例如,a += b等价于a = a + b

  • -=:减法赋值运算符

将右操作数的值从左操作数中减去,并将结果赋给左操作数。

例如,a -= b等价于a = a - b

  • *=:乘法赋值运算符

将右操作数的值乘以左操作数,并将结果赋给左操作数。

例如,a *= b等价于a = a * b

  • /=:除法赋值运算符

将左操作数的值除以右操作数,并将结果赋给左操作数。

例如,a /= b等价于a = a / b

  • %=:取模赋值运算符

将左操作数的值除以右操作数得到的余数,并将结果赋给左操作数。

例如,a %= b等价于a = a % b

6.数据的输出

6.1⽤ printf函数输出数据

cpp 复制代码
printf(格式控制, 输出列表);
//举例
int i = 10;
char c = '0';
printf("%d,%c\n",i,c);
//格式控制":是⽤英⽂双引号括起来的⼀个字符串,称为格式控制字符串,简称格式字符串

6.2格式字符

  • d 、i 格式字符:⽤于输出有符号⼗进制整数
  • u 格式符:⽤于输出⽆符号⼗进制整数
  • f 格式符:⽤于输出浮点数

指定数据宽度和⼩数位数,⽤ %m.nf

输出的数据向左对⻬,⽤ %-m.nf

m代表输出的数据占⼏位,n代表输出⼏位⼩数

cpp 复制代码
float x = 3.14159;
printf("%-8.2f\n", x);
//m代表输出的数据占⼏位,n代表输出⼏位⼩数,- 代表向左对⻬
  • c 格式符:⽤于输出字符

s 格式符:⽤于输出字符串

cpp 复制代码
char str[] = "Hello, World!";
printf("%s\n", str); // 输出:Hello, World!
  • p 格式符:⽤于输出指针地址
cpp 复制代码
int* ptr = #
printf("%p\n", ptr); // 输出:0x7ffeed56a9c4 (根据具体内存地址⽽定)
  • %x:⽤于输出⼗六进制整数(⼩写字⺟)
  • %X:⽤于输出⼗六进制整数(⼤写字⺟)
  • %o:⽤于输出⼋进制整数
  • %e:⽤于输出科学计数法表示的浮点数(⼩写字⺟)
  • %E:⽤于输出科学计数法表示的浮点数(⼤写字⺟)
  • %g:根据数值的⼤⼩⾃动选择使⽤%f或%e格式输出浮点数(⼩写字⺟)
  • %G:根据数值的⼤⼩⾃动选择使⽤%f或%E格式输出浮点数(⼤写字⺟)
  • %%:⽤于输出百分号

7.数据的输入

7.1scanf函数输⼊数据

可能不读取空格间断情况

**&**运算符⽤于获取变量的地址。当我们在 scanf中使⽤ **&**运算符时,它表示我们要将变量
的地址传递给 scanf函数,以便它可以直接修改变量的值。

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS//头部要包含
scanf(格式控制,地址列表);

int num;
scanf("%d", &num); // 使⽤ & 获取 num 的地址,并将⽤户输⼊的值存储在 num 中
char str[20];
scanf("%s", str);//str是一个数组 退化成指针

7.2格式声明

以 % 开始,以⼀个格式字符结束

  • d 、i 格式符:输⼊有符号的⼗进制整数
  • u 格式符:输⼊⽆符号的⼗进制 ● o 格式符:输⼊⽆符号的⼋进制
  • x 、X 格式符:输⼊⽆符号的⼗六进制整数(⼤⼩写作⽤相同)
  • e 格式符:输⼊单个字符
  • s 格式符:

输⼊字符串,将字符串送到⼀个字符数组中,在输⼊时以⾮空⽩字符开始,以第⼀个空⽩字符结束。

字符串以标志 '\0' 作为其Y后⼀个字符

  • f 格式符:输⼊实数,可以⽤⼩数形式或指数形式输⼊
  • e 、E 、g 、G 格式符:与 f 作⽤相同,e 与 f 、g 可以互相替换(⼤⼩写作⽤相同)

8.fgets读取一行数据

读取空格间断情况

cpp 复制代码
char str[20];

fgets(str,20,stdin);//从stdin中读取一行到str,最大长度是20

printf("str = %s\n", str);

9.字符输⼊输出函数

putchar 函数输出⼀个字符

cpp 复制代码
putchar(c); // c为⼀个字符 1

getchar 函数输⼊⼀个字符

cpp 复制代码
char a;
a = getchar(); // 从键盘输⼊⼀个字符,传给字符变量a

三、选择结构程序设计

1、关系运算符

  • 相等:==
  • 不等:!=
  • ⼤于:>
  • ⼩于:<
  • ⼤于等于:>=
  • ⼩于等于:<=

2、逻辑运算符

  • 逻辑与:&&
  • 逻辑或:||
  • 逻辑⾮:!

3、条件运算符(三目运算符)

cpp 复制代码
a ? b : c
//如果条件a表达式为真,则整个表达式的值为 b ;如果条件表达式为假,则整个表达式的值
为 c。

4、if语句

cpp 复制代码
if (condition) {
 // 当condition为真时执⾏的代码
 }

5、if-else语句

cpp 复制代码
if (condition) {
 // 当condition为真时执⾏的代码
 } else {
 // 当condition为假时执⾏的代码
}

6、if-else if语句

cpp 复制代码
if (condition1) {
 // 当condition1为真时执⾏的代码
 } else if (condition2) {
 // 当condition2为真时执⾏的代码
 } else {
 // 当所有条件都为假时执⾏的代码
}

7、switch break 语句

cpp 复制代码
switch (表达式) {
 case 值1:
 // 如果表达式匹配值1,则执⾏这⾥的代码
 break;
 case 值2:
 // 如果表达式匹配值2,则执⾏这⾥的代码
 break;
 case 值3:
 // 如果表达式匹配值3,则执⾏这⾥的代码
 break;
 ...
 default:
 // 如果表达式不匹配任何值,则执⾏这⾥的代码
}

四、循环结构程序设计

1.while 循环

cpp 复制代码
while (条件) {
 // 要执⾏的代码
}

2.do while 循环

先执⾏⼀次循环体代码,然后再检查条件是否满⾜

cpp 复制代码
do {
 // 循环体代码
} while (条件);

3.for 循环

cpp 复制代码
for (初始化语句; 循环条件; 迭代语句) {
 // 循环体代码
}

5.break、continue作⽤

break 语句 ⽤于中断当前所在的循环结构,即在满⾜某个条件时提前跳出循环,结束循环的执⾏。
continue语句⽤于终⽌当前循环迭代中的剩余语句,并进⼊下⼀次循环迭代
数组

五、数组

(一)、一维数组

数组的⻓度是固定的,⼀旦定义后就不能改变。
可⽤于存储⼀系列相同类型的元素。

数组可以在内存中连续存储多个元素,并通过索引(或者叫下标)来访问和操作这些元素。

cpp 复制代码
数组的定义形式: 数据类型 数组名[数组⻓度];  

数据类型指定了数组中元素的类型,数组名是数组的标识符,数组⻓度指定了数组可以存储的元素个数。

1.数组的初始化

cpp 复制代码
//静态初始化:在定义时就定义了所有数据
int numbers[5] = {1, 2, 3, 4, 5}; 
//动态初始化:先定义数组,再后续定义数据
int numbers[5];
numbers[0] = 1;
numbers[1] = 2;
numbers[2] = 3;
numbers[3] = 4;
numbers[4] = 5;

2.数组的访问

.使⽤索引(或者叫下标)来访问数组中的元素。
数组的索引(或者叫下标)从0开始递增,表示数组中元素的位置。
访问数组元素的⽅式为: 数组名****索引****。

(二)、二维数组

⼆维数组可以看作是⼀个表格或矩阵,它由⾏和列组成。

1.⼆维数组的定义

cpp 复制代码
维数组的定义形式: 数据类型 数组名[⾏数][列数];

2.⼆维数组的初始化

cpp 复制代码
//静态初始化:int str[2][3] = {{1,2,3},{4,5,6}};
//将所有数据写在同⼀花括号内:系统按照下标⾃动⾃动分配⾏列
int str[2][3] = {1,2,3,4,5,6};
int str[2][3] = {{1,2,3},{4,5,6}}; //两者均表示⼀个意思
//只对部分元素赋值:未赋值的元素⾃动赋值为 0
//定义时,可以对第⼀维不指定,但第⼆维必须指定:
int str[2][3] = {1,2,3,4,5,6};
//等价于
int str[][3] = {1,2,3,4,5,6}; //第⼆维为三,总共有6个数据,所以第⼀维⾃然为⼆

3.⼆维数组的访问

访问数组元素的⽅式为: 数组名****索引****索引****。

(三)、字符数组

C语⾔中没有字符串类型,也没有字符串变量,字符串时存放在字符型数组中的。

**1.**字符数组的定义

cpp 复制代码
char str[6];
str[0] = 'H';
str[1] = 'e';
str[2] = 'l';
str[3] = 'l';
str[4] = 'o';
str[5] = '\0'; //添加结束字符'\0',表示字符串结束,⻢上就讲到
printf("%s",str);

**2.**字符数组的初始化

cpp 复制代码
//静态初始化:
char str[5] = {'H','e','l','l','o'};
//两者同⼀个意思
char str[] = {'H','e','l','l','o'};

**3.**字符数组的访问

访问字符数组时,可以使⽤索引来访问数组中的每个字符。索引从0开始,递增到数组⻓度减1。

**4.**字符串和字符串结束标志

字符串结束标志
C语⾔规定,以字符 '\0' 作为结束标志。

5.字符数组的输⼊输出

逐个字符输⼊输出,⽤格式符 '%c':

cpp 复制代码
char str[20];
int i;
printf("请输⼊⼀个字符串:");
for(i = 0; i < 20; i++) {
 scanf("%c", &str[i]);
 if(str[i] == '\n') {
 str[i] = '\0'; // 将换⾏符替换为字符串结束符
 break;
 }
}

将整个字符串⼀次性输⼊输出,⽤格式符 '%s':.

**6.**字符串处理函数

6.1puts 函数------输出字符串函数
cpp 复制代码
char str[10] = "China";
puts(str);//输出China
//同时,puts函数输出的字符串可以包含转义字
char str[] = "Hello\nChina";
puts(str);
//Hello
//China
在⽤puts输出时将字符串结束标志'\0'转换成'\n',即输出完字符串后换⾏
6.2gets 函数------输⼊字符串函数

从终端输⼊⼀个字符串到字符数组,并且得到⼀个返回值。
返回值:如果成功,返回输⼊的字符串;如果发⽣错误或到达⽂件结束,返回 NULLstrncpy 函数⽤于将⼀个字符串的指定⻓度复制到另⼀个字符串中
strncpy(字符串1, 字符串2, 要复制的字符数);

cpp 复制代码
char str[100];
gets(str); \\假定输⼊China
//输出China
6.3strcat函数------字符串连接函数
cpp 复制代码
strcat(字符数组1,字符数组2); //把字符串2连接到字符串1的后⾯

har destination[20] = "Hello";
char source[] = " World!";
 
strcat(destination, source);
printf("%s\n", destination);

//输出Hello world!
6.4strcpy函数------字符串复制函数
cpp 复制代码
//strcpy(字符数组1,字符数组2); //将字符串2复制到字符串1中去

char str1[10], str2[] = "China";
strcpy(str1,str2);
printf("%s",str1);            //输出China
6.5strncpy 函数⽤于将⼀个字符串的指定⻓度复制到另⼀个字符串中
cpp 复制代码
strncpy(字符串1, 字符串2, 要复制的字符数);
需要注意的是, strncpy 函数不会⾃动在⽬标字符串的末尾添加结束符 \0 ,因此在使⽤ str
ncpy 函数后,需要⼿动将结束符 \0 添加到⽬标字符串的末尾。

#include <stdio.h>
#include <string.h>
int main() {
 char str1[10];
 char str2[] = "Hello, World!";
 
 strncpy(str1, str2, sizeof(str1)-1);
 str1[sizeof(str1)-1] = '\0'; // ⼿动添加结束符\0
 
 printf("strncpy: %s\n", str1);
 
 return 0;
}
6.6strcmp函数------字符串⽐较函数
cpp 复制代码
strcmp(字符串1, 字符串2);
char str1 = "Hello";
char str2 = "world";
strcmp(str1,str2);
strcmp("China","Korea");
strcmp("China",str1);

⽐较规则:

  • 将两字符串⾃左⾄右逐个字符相⽐(按ASCII码值⼤⼩⽐较),直到出现不同的字符或遇到
  • '\0'为⽌
  • 如全部字符相同,则认为两字符串相等
  • 若出现不相同的字符,则以第1对不相同的字符的⽐较结果为准。
  • eg:"DOG">"cat"

⽐较的结果由函数值带回:

  • 如字符串1与字符串2相同,则函数值为0
  • 如字符串1>字符串2,则函数值为⼀个正整数
  • 如字符串1<字符串2,则函数值为⼀个负整数
6.7strlen 函数------测字符串⻓度的函数
cpp 复制代码
strlen(字符数组);
函数的值为字符串中的实际⻓度(不包括 '\0' 在内)
char str[10] = "China";
printf("%d",strlen(str))//返回5
6.8strlwr 函数------转换为⼤写的函数
cpp 复制代码
strlwr(字符串);
6.9strupr 函数------转换为⼤写的函数
cpp 复制代码
strupr(字符串);

六、函数

1.定义函数

形式参数:再定义函数时函数名后⾯括号中的变量名称 为"形式参数"(简称"形参")或"虚
拟参数"
实际参数:再主调函数中调⽤⼀个函数时,函数名后⾯括号中的参数称为"实际参数"(简
称"实参")

1.1定义⽆参函数

cpp 复制代码
类型名 函数名()
{
函数体
}
// 或者
类型名 函数名(void)
{
函数体
}

1.2定义有参函数

cpp 复制代码
类型名 函数名(形参)
{
函数体
}

1.3定义空函数

cpp 复制代码
类型名 函数名()
{ }

2.调用函数

cpp 复制代码
函数名 (实参列表);
函数调⽤的3种形式:

    1.函数调⽤语句:
把函数调⽤单独作为⼀个语句。:printf_ns();
    2.函数表达式:是表达式的⼀部分,来参与表达式的运算
c = 2 * max(a,b); //求出a,b之间的最⼤值,再与2进⾏计算
    3.函数参数:函数调⽤作为另⼀个函数调⽤时的参数
m = max(a,max(b,c));

3.函数递归

C语⾔允许在调⽤⼀个函数的过程中有出现直接或间接地调⽤该函数本身,这种⾏为称为函数的递
归调⽤
在C语⾔中,函数递归的实现需要满⾜以下⼏个要点:

  1. 基本情况(递归终⽌条件):递归函数必须包含⼀个或多个基本情况,即递归终⽌条件。这 些条件表示递归函数不再继续调⽤⾃身,⽽是直接返回⼀个结果。没有递归终⽌条件的递归函
    数将会⽆限循环调⽤⾃身,导致栈溢出。
  2. 递归调⽤:在递归函数的定义中,通过调⽤⾃身来解决规模更⼩的⼦问题。递归调⽤应该在
    满⾜递归终⽌条件的情况下进⾏,以避免⽆限递归。
  3. 问题规模的缩⼩:递归函数应该在每次调⽤⾃身时,通过改变输⼊参数的值来缩⼩问题的规 模。这样,每次递归调⽤都在解决⼀个规模更⼩的⼦问题。
    阶乘递归案例
cpp 复制代码
#include <stdio.h>
// 递归函数,计算阶乘
int factorial(int n) {
 // 基本情况:当n为0或1时,直接返回1
 if (n == 0 || n == 1) {
 return 1;
 }
 
 // 递归调⽤:将问题规模缩⼩,计算n的阶乘需要先计算(n-1)的阶乘
 return n * factorial(n - 1);
}
int main() {
 int num = 5;
 
 // 调⽤递归函数计算阶乘
 int result = factorial(num);
 
 // 设置中⽂环境
 setlocale(LC_ALL, "");
 // 打印结果
 wprintf(L"%d的阶乘是:%d\n", num, result);
 
 return 0;
}

4.数组作为函数参数

在⽤数组元素作函数实参时,把实参的值传给形参,是"值传递"⽅式。

数组元素也可以⽤作函数实参,⽤法与变量⼀致,向形参传递数组元素的值。属于值传递

数组元素可以⽤作函数实参,但是不能⽤作形参

cpp 复制代码
#include <stdio.h>
void changeValue(int num) {
 num = 10;
}
int main() {
 int array[5] = {1, 2, 3, 4, 5};
 printf("调⽤函数前: %d\n", array[0]);
 changeValue(array[0]);
 printf("调⽤函数后: %d\n", array[0]);
 return 0;
}

结果 1 1

4.2数组名做函数参数

除了可以⽤数组元素作为函数参数外,还可以⽤数组名作函数参数(包括实参和形参)
⽤数组元素作实参时,向形参变量传递的事数组元素的值,⽽⽤数组名作函数实参时,向形参
(数组名或指针变量)传递的事数组⾸元素的地址

cpp 复制代码
#include <stdio.h>
void printArray(int arr[], int size) {
	for (int i = 0; i < size; i++) {
		printf("%d ", arr[i]);
	}
	printf("\n");
}
void changeArray(int arr[], int size) {
	for (int i = 0; i < size; i++) {
		arr[i] = arr[i] * 2;
	}
}
int main() {
	int array[5] = { 1, 2, 3, 4, 5 };
	printf("调⽤函数前:");
	printArray(array, 5);
	changeArray(array, 5);
	printf("调⽤函数后:");
	printArray(array, 5);
	return 0;
}



在函数调⽤时,我们将数组名 array 作为实参传递给了函数的形参,即 printArray(arra
y, 5) 和 changeArray(array, 5) 。由于数组名传递的是数组⾸元素的地址,函数在接收
到数组名后,可以通过指针的⽅式访问数组的元素,并对其进⾏操作。
输出结果:
调⽤函数前:1 2 3 4 5
调⽤函数后:2 4 6 8 10

5.局部变量的存储类别

C语⾔的存储变量分为⾃动变量(auto)、静态变量(static)、寄存器变量(register)、外部变
量(extern) 局部变量分为以

  • ⾃动变量(auto变量)
cpp 复制代码
void f() {
 auto int x = 10;
 // ...
}

关键字 auto可以省略,不写 auto 则隐含指定为"⾃动存储类别",它属于动态存储
⽅式。
  • 静态局部变量(static局部变量)
  • 有时希望函数中的局部变量的值在函数调⽤结束后不消失,⽽继续保留原值,其占⽤的储存单元不释放,在下⼀次在调⽤该函数时,该变量已有值(就是上⼀次调⽤结束时的值)。
cpp 复制代码
#include <stdio.h>
void increment() {
 static int count = 0; // 静态局部变量
 count++;
 printf("Count: %d\n", count);
}
int main() {
 increment(); // 输出 Count: 1
 increment(); // 输出 Count: 2
 increment(); // 输出 Count: 3
 return 0;
}

6.全局变量存储类别

如果外部变量不在⽂件的开头定义,其有效地作⽤范围值限于定义处到⽂件结束。在定义点之 前的函数不能引⽤该外部变量。如果由于某种考虑,在定义之前的函数需要引⽤该外部变量,则应 该在应⽤之前⽤关键字 extern 对该变量作"外部变量声明",表示把该外部变量的作⽤域扩展到此 位置。有了此声明,就可以从"声明"处起,合法地使⽤外部变量
.

cpp 复制代码
#include <stdio.h>
int x = 10; // 定义全局变量x
void foo(); // 声明函数foo
int main() {
 foo(); // 调⽤函数foo
 printf("x = %d\n", x); // 打印全局变量x的值
 return 0;
}

//使⽤extern关键字声明变量x
#include <stdio.h>
extern int x; // 使⽤extern关键字声明全局变量x
void foo() {
 printf("Inside foo: x = %d\n", x); // 打印全局变量x的值
 x = 20; // 修改全局变量x的值
}

将外部变量的作⽤域拓展找其他⽂件

cpp 复制代码
//⽂件a.c中定义外部变量x:
#include <stdio.h>
int x = 10; // 定义外部变量x
int main() {
 printf("x = %d\n", x); // 打印外部变量x的值
 return 0;
}
//在⽂件b.c中使⽤extern关键字引⽤外部变量x:
#include <stdio.h>
extern int x; // 使⽤extern关键字引⽤外部变量x
void foo() {
 printf("Inside foo: x = %d\n", x); // 打印外部变量x的值
 x = 20; // 修改外部变量x的值
}

7.内部函数

如果⼀个函数只能被本⽂件其他函数所调⽤,它称为内部函数。在定义内部函数时,在函数名
和函数类型的前⾯加 static 即可

cpp 复制代码
static 类型名 函数名(形参表)

8**.**外部函数

如果在定义函数时,在函数⾸部的最左段加关键字extern,则此函数时外部函数,可供其他⽂
件调⽤。

cpp 复制代码
extern int fun(int a,int b);

如果在定义函数时省略 extern,则默认为外部函数。

七、指针

相关推荐
栈溢出了1 小时前
LangGraph State 学习笔记
开发语言·人工智能·python
HEJOO91 小时前
Go 语言结构体定义与实例详解
开发语言·算法·golang
(Charon)1 小时前
【C++面试】手写智能指针(一):从unique_ptr理解独占所有权与移动语义
开发语言·c++
每天题库1 小时前
汽车维修工考试题库:真题错题复盘与高频考点清单
学习·安全·考试·题库·考证
Brilliantwxx1 小时前
【STM32】 DMA 源码分析与实战(下):DMA 收发状态机与 HAL 分层
android·开发语言·stm32·单片机·嵌入式硬件·mcu
Ai-_Man1 小时前
请问豆包的智能体聊天记录该怎么弄
开发语言·前端·javascript·人工智能·小程序·ecmascript·电脑
阳光九叶草LXGZXJ2 小时前
达梦数据库-学习-71-存过执行过程中重建存过影响验证
linux·运维·数据库·sql·学习
言乐62 小时前
Python根据关联词搜索模型
开发语言·人工智能·python·机器学习·django
纪念 2292 小时前
C++ string(一)
android·开发语言·c++