C语言核心知识(第一部分:关键字、基础语法、数据类型)
一、C语言32个关键字分类
1.1 数据类型关键字(12个)
// 基本类型
char // 字符型,1字节
int // 整型,通常4字节
float // 单精度浮点,4字节
double // 双精度浮点,8字节
void // 空类型
// 类型修饰符
short // 短整型
long // 长整型
signed // 有符号
unsigned // 无符号
// 构造类型
struct // 结构体
union // 共用体
enum // 枚举
1.2 存储类关键字(5个)
auto // 自动变量(默认)
extern // 外部变量声明
register // 寄存器变量
static // 静态变量
typedef // 类型重定义
1.3 控制语句关键字(12个)
// 条件语句
if
else
switch
case
default
// 循环语句
for
while
do
// 跳转语句
break
continue
goto
return
1.4 其他关键字(3个)
const // 只读常量
volatile // 易失性变量
sizeof // 求大小运算符
二、关键字的详细用法
2.1 static关键字(最重要)
// 1. 静态局部变量 - 生命周期延长
void test() {
static int count = 0; // 只初始化一次!
count++;
printf("调用次数:%d\n", count);
}
// test()第一次调用输出1,第二次输出2,第三次输出3
特点总结:
-
只初始化一次,程序运行期间一直存在
-
存储在静态存储区(不是栈区)
-
作用域仅限于定义它的函数内部
// 2. 静态全局变量 - 作用域限制
static int hidden = 100; // 只能在当前文件访问
// 3. 静态函数 - 作用域限制
static void secret() { // 只能在当前文件调用
printf("私有函数\n");
}
2.2 const与volatile
// const:定义常量
const int MAX = 100; // 常量
const int* p1 = &a; // 指向常量的指针(值不可变)
int* const p2 = &a; // 常量指针(指向不可变)
const int* const p3 = &a; // 都不可变
// volatile:防止编译器优化
volatile int flag = 0; // 每次都从内存读取
while(flag == 0) { // 不会优化成无限循环
// 等待外部改变flag
}
2.3 extern与register
// extern:跨文件使用变量
// file1.c
int global = 100; // 定义全局变量
// file2.c
extern int global; // 声明外部变量
printf("%d", global); // 输出100
// register:建议使用寄存器
register int i; // 快速访问的局部变量
for(register i=0; i<10000; i++) {
// 频繁使用的循环变量
}
三、基本数据类型
3.1 整数类型
| 类型 | 字节 | 范围(有符号) | 范围(无符号) |
|---|---|---|---|
| char | 1 | -128 ~ 127 | 0 ~ 255 |
| short | 2 | -32768 ~ 32767 | 0 ~ 65535 |
| int | 4 | -2.1e9 ~ 2.1e9 | 0 ~ 4.2e9 |
| long | 4/8 | -2.1e9~9.2e18 | 0~1.8e19 |
3.2 浮点类型
float f = 3.14f; // 单精度,6-7位有效数字
double d = 3.1415926; // 双精度,15-16位有效数字
long double ld = 3.14L; // 扩展精度
3.3 void类型
// 1. 函数无返回值
void func(void) {
// 没有返回值
}
// 2. 函数无参数
int get_value(void) {
return 100;
}
// 3. void指针
void* ptr; // 通用指针
ptr = &int_var;
ptr = &char_var;
四、运算符与表达式
4.1 算术运算符
+ - * / % // 加 减 乘 除 取余
++ -- // 自增 自减
// 注意整数除法
int a = 5 / 2; // 结果是2,不是2.5
float b = 5.0 / 2; // 结果是2.5
4.2 关系运算符
> >= < <= // 大于 大于等于 小于 小于等于
== != // 等于 不等于
4.3 逻辑运算符
c
&& || ! // 与 或 非
// 短路特性
if(a>0 && b>0) // 如果a<=0,b>0不会判断
if(a>0 || b>0) // 如果a>0,b>0不会判断
4.4 位运算符
& | ^ ~ // 与 或 异或 取反
<< >> // 左移 右移
// 示例
unsigned char a = 0b00101100;
unsigned char b = 0b00001111;
a & b = 0b00001100 // 按位与
a | b = 0b00101111 // 按位或
a ^ b = 0b00100011 // 按位异或
~a = 0b11010011 // 按位取反
a << 2 = 0b10110000 // 左移2位
a >> 2 = 0b00001011 // 右移2位
4.5 赋值运算符
= += -= *= /= %=
&= |= ^= <<= >>=
4.6 其他运算符
sizeof() // 求字节大小
(type) // 强制类型转换
? : // 三目运算符
& // 取地址
* // 解引用
. // 结构体成员
-> // 结构体指针成员
[] // 数组下标
() // 函数调用
五、控制语句
5.1 条件语句
// if-else
if(score >= 90) {
grade = 'A';
} else if(score >= 80) {
grade = 'B';
} else {
grade = 'C';
}
// switch-case
switch(level) {
case 1:
printf("初级\n");
break;
case 2:
printf("中级\n");
break;
case 3:
printf("高级\n");
break;
default:
printf("未知等级\n");
}
5.2 循环语句
// for循环
for(int i=0; i<10; i++) {
printf("%d ", i);
}
// while循环
int i = 0;
while(i < 10) {
printf("%d ", i);
i++;
}
// do-while循环
int i = 0;
do {
printf("%d ", i);
i++;
} while(i < 10);
5.3 跳转语句
// break - 跳出循环或switch
for(int i=0; i<10; i++) {
if(i == 5) break;
printf("%d ", i); // 输出0 1 2 3 4
}
// continue - 跳过本次循环
for(int i=0; i<10; i++) {
if(i == 5) continue;
printf("%d ", i); // 输出0 1 2 3 4 6 7 8 9
}
// goto - 跳转到标签
if(error) {
goto cleanup;
}
// ... 正常代码
cleanup:
free(resource);
return;
六、输入输出函数
6.1 标准输入输出
#include <stdio.h>
// 输出函数
printf("格式字符串", 参数); // 格式化输出
puts("字符串"); // 输出字符串并换行
putchar('A'); // 输出单个字符
// 输入函数
scanf("格式", &变量); // 格式化输入
gets(字符串); // 读取一行(不安全)
getchar(); // 读取单个字符
// 格式说明符
%d // 十进制整数
%f // 浮点数
%c // 字符
%s // 字符串
%p // 指针
%x // 十六进制
%o // 八进制
6.2 示例
int age;
float score;
char name[20];
printf("请输入姓名、年龄、成绩:");
scanf("%s %d %f", name, &age, &score);
printf("姓名:%s\n", name);
printf("年龄:%d\n", age);
printf("成绩:%.2f\n", score);
七、预处理指令
7.1 文件包含
#include <stdio.h> // 系统头文件
#include "myheader.h" // 用户头文件
7.2 宏定义
// 对象宏
#define PI 3.1415926
#define MAX 100
// 函数宏
#define SQUARE(x) ((x)*(x))
#define MAX(a,b) ((a)>(b)?(a):(b))
// 多行宏
#define SWAP(a,b) do { \
typeof(a) temp = a; \
a = b; \
b = temp; \
} while(0)
7.3 条件编译
#ifdef DEBUG
printf("调试模式\n");
#endif
#ifndef HEADER_H
#define HEADER_H
// 头文件内容
#endif
#if VERSION > 2
// 版本2以上的代码
#elif VERSION == 2
// 版本2的代码
#else
// 旧版本代码
#endif
7.4 其他指令
#undef PI // 取消宏定义
#pragma once // 防止头文件重复包含
#line 100 "newfile.c" // 修改行号和文件名
#error "编译错误" // 产生编译错误
#pragma message("信息") // 编译时显示信息
八、类型定义typedef
8.1 基本用法
// 为现有类型创建别名
typedef int INT32;
typedef unsigned char BYTE;
typedef float FLOAT32;
// 使用
INT32 a = 100;
BYTE b = 0xFF;
FLOAT32 c = 3.14f;
8.2 复杂类型定义
// 数组类型
typedef int INT_ARRAY[10];
INT_ARRAY arr; // 等价于 int arr[10];
// 函数指针类型
typedef int (*COMPARE_FUNC)(int, int);
COMPARE_FUNC cmp = compare;
// 结构体类型
typedef struct {
int x;
int y;
} POINT;
POINT p1, p2; // 直接使用,不需要struct关键字
九、类型转换
9.1 隐式类型转换
// 自动转换规则:低精度→高精度
char → short → int → long → float → double
int a = 10;
float b = 3.14;
float c = a + b; // a自动转换为float
// 整数提升
char c1 = 100, c2 = 100;
int result = c1 * c2; // char提升为int
9.2 显式类型转换
// C风格
int a = 10;
float b = (float)a / 3; // 强制转换
// 注意指针转换
int *p = (int*)malloc(sizeof(int));
void *vp = (void*)p;
// 浮点转整数
float f = 3.8;
int i = (int)f; // i=3,直接截断
9.3 类型转换注意事项
// 1. 有符号与无符号混合
int a = -1;
unsigned int b = 100;
if(a > b) { // a被转换为无符号,结果很大
printf("这会发生!\n");
}
// 2. 浮点精度丢失
float f = 0.1;
if(f == 0.1) { // 0.1默认是double,比较会出问题
printf("这不会发生!\n");
}
// 正确做法
if(fabs(f - 0.1) < 0.00001) {
printf("浮点数相等\n");
}