1.头文件含义(C 语言的.h文件类似于java的interface,只是声明函数,并不实现函数)
在C语言编程中,头文件扮演着至关重要的角色。它们是扩展名为 .h 的文件,包含了C函数声明和宏定义,用于在多个源文件之间共享代码。
头文件允许程序员在不同的源文件中重用相同的代码,而无需重复编写代码。
头文件的作用:
头文件的主要作用是提供接口
。例如,当你在代码中使用 printf 函数时,实际上是在调用 stdio.h 头文件中定义的函数。如果没有包含相应的头文件,编译器将不知道 printf 是什么,从而无法编译代码。因此,头文件可以看作是一个预先准备好的代码库,你可以从中选择需要的功能来提高代码效率。
stdio.h解释:是C语言标准库中的一个头文件,它定义了处理文件和标准输入/输出流的各种函数和类型。这个库提供了一系列的变量类型、宏定义和函数,用于执行输入和输出操作
。
std:标准库
i:input
o:output
2.全局变量
2.1全局变量的作用范围是整个工程
其他.c定义的全局变量,此.c文件想调用时,用extern 数据类型 全面变量名
即可调用
2.2局部变量生命周期
执行进入{就是开始创建,执行到}就是销毁
2.2全局变量生命周期
整个程序运行中都存在,程序关闭即销毁
3.字符串的结束标志
\0
:是字符串的结束标志,指的是读取字符串时遇到转义字符\0
就停止
4.占位符理解
占位符(Placeholder)是什么意思?
在 printf 和其他格式化输出函数中,占位符(Placeholder) 指的是格式字符串中以 % 开头的部分(如 %d、%f、%s 等),它表示“这里要插入一个变量的值”。
为什么叫“占位符”?
“占位”:它在字符串中占据一个位置,告诉程序“稍后这里要替换成一个实际的值”。
“符”:它是一个特殊的符号(如 %d),代表某种数据类型。
5.转义字符理解
转义字符(Escape Character) 在 C 语言中主要有两个作用:
-
表示无法直接输入/显示的字符(如换行、制表符、引号等)。这样就能正常打印“
printf("他说:\"你好\""); // 正确,输出:他说:"你好"
-
执行特殊功能(如换行 \n、响铃 \a 等)。
6.GCC理解
GCC 不是一个单一的编译器,而是一个编译器套件
GCC 是编译器集合
gcc 只是其 C 语言的驱动程序
作用:GCC 不仅是 C 编译器,还是支持多语言(go/Objective-C/C++等语言)的完整工具链,其 gcc 命令专门处理 C 代码,但背后依赖预处理、编译、汇编、链接等多个组件。
关键组件:
cc1:C 编译器核心(gcc 调用它)。
cc1plus:C++ 编译器核心(g++ 调用它)。
libgcc:GCC 的底层运行时库。
libc : C 标准库(如 printf、malloc,通常指 glibc 或 musl)
7.g++理解
关键组件:
libstdc++:C++ 标准库实现。
g++ 是 GCC 中专门针对 C++ 的驱动程序(Driver)
使用 g++ 的完整流程(hello是可执行程序,可直接运行)
g++ hello.cpp -o hello
实际步骤:
预处理:cpp hello.cpp > hello.ii(展开宏、头文件)。
编译:cc1plus hello.ii -o hello.s(生成汇编)。
汇编:as hello.s -o hello.o(生成目标文件)。
链接:ld hello.o -lstdc++ -o hello(自动链接 C++ 库)。
8.单目操作符(前置++和后置++的区分)
前置++ :
int a = 5;
int b = ++a;//(前置++ :先a+1,后赋值)
所以a = 6 ,b = 6
后置++ :
int a = 5;
int b = a++;//(后置++ :先赋值给b,再a+1)
所以a = 6 ,b = 5
9.C语言中static关键字的用法总结(全局变量的时候作用域与java的static正好相反)
.c文件中的全局变量/函数默认是外部链接的!其他.c文件可以外部引用
1.在函数内部(局部变量)
作用:将局部变量变为静态存储期变量
特点:
变量在程序运行期间一直存在(不像自动变量随函数调用结束而消失);
只在第一次进入函数时初始化一次(配合使用单例模式);
保持上次函数调用结束时的值;
作用域限于定义它的函数内部;
void counter() {
static int count = 0; // 只初始化一次
count++;
printf("Count: %d\n", count);
}
int main() {
counter(); // 输出 Count: 1
counter(); // 输出 Count: 2
counter(); // 输出 Count: 3
return 0;
}
2.在函数定义(函数本身)
作用:限制函数的作用域为当前文件(将外部链接改成了内部链接,只能在该.c文件中使用),没用static修饰的函数,其他.c源文件都可以调用
特点:
使函数成为文件作用域的(只能在定义它的源文件中使用)
避免与其他文件中的同名函数冲突
隐藏函数实现细节(封装)
// file1.c
static void helper() { // 只能在本文件使用
printf("Helper function\n");
}
// file2.c
static void helper() { // 这是另一个不同的函数
printf("Different helper\n");
}
3. 在文件作用域(全局变量)
作用:限制全局变量的作用域为当前文件
特点:
变量具有静态存储期(整个程序运行期间存在)
作用域限于定义它的文件(内部链接)
避免命名空间污染
// file1.c
static int fileLocal = 42; // 只能在本.c文件中访问
// file2.c
extern int fileLocal; // 错误!!!编译不能通过,无法访问另一个文件的static全局变量
10.宏的理解
宏(Macro)是C语言预处理器提供的一种功能,它允许你在编译前对代码进行文本替换
。
-
对象式宏(Object-like Macro)
c
#define PI 3.14159
这种宏在代码中简单地将PI替换为3.14159。 -
函数式宏(Function-like Macro)
c
#define SQUARE(x) ((x) * (x))
这种宏看起来像函数调用,但实际上是文本替换。
11.C中的指针理解
调用函数传的值叫实参,函数的参数叫形参!
- java代码
这里的p相当于 Person p = person;(创建对person的引用副本)
void modifyObject(Person p) {
p.name = "Alice"; // 修改对象属性(生效)
p = new Person("Bob"); // 修改的是引用的副本,不影响原始引用
}
Person person = new Person("John");
modifyObject(person);
System.out.println(person.name); // 输出 "Alice"
- C的值传递
#include <stdio.h>
#include <string.h>
typedef struct {
char name[50];
} Person;
这里的p相当于重新创建一个 Person ,然后复制person的值进来!!!
void modifyObject(Person p) {
strcpy(p.name, "Alice"); // 修改的是副本,不影响原始数据
Person newPerson = { "Bob" };
p = newPerson; // 修改副本,不影响原始数据
}
int main() {
Person person = { "John" };
modifyObject(person);
printf("%s\n", person.name); // 输出 "John"(未被修改)
return 0;
}
- C的引用传递
这里的p是person的地址,知道地址就什么都能修改
void modifyObject(Person *p) {
strcpy(p->name, "Alice"); // 修改原始数据
Person newPerson = { "Bob" };
*p = newPerson; // 修改原始数据(现在 Alice 变成 Bob),复制 newPerson 的所有数据到 person。
}
int main() {
Person person = { "John" };
modifyObject(&person); // 传递指针
printf("%s\n", person.name); // 输出 "Bob"(被修改)
return 0;
}
行为 | Java (对象引用) | C (结构体副本) | C (指针) |
---|---|---|---|
参数传递方式 | 引用的副本(类似指针的引用传递,但是只能影响原始对象的 值 !!!) | 完整结构体的值拷贝 | 指针的引用传递(用指针) |
修改属性 | ✅影响原始对象(p.name = “Alice”) | ❌ 不影响原始结构体 | ✅ 影响原始结构体数据(p->name = “Alice”) |
重新赋值 | ❌ 不影响原始引用(p = new Person()) | ❌ 不影响原始结构体(p = { “Bob” }) | ✅ 影响原始结构体数据,不影响地址!!! (*p = { “Bob” }) |
看到43!