1 C语言介绍
C语言是一种通用的编程语言,由Dennis Ritchie在1970年代初期开发。它的主要特点包括:
高效性:C语言能够生成高效的机器代码,适合系统编程和嵌入式开发。
灵活性:C语言支持多种编程范式,包括过程式编程和结构化编程。
可移植性:C语言编写的程序可以在不同的平台上编译和运行,具有良好的可移植性。
丰富的库:C语言提供了丰富的标准库,支持各种常用的操作和功能。
底层操作:C语言允许对内存进行直接操作,适合开发操作系统和驱动程序等底层软件。
C语言广泛应用于系统软件、应用程序、游戏开发和嵌入式系统等领域,是许多现代编程语言的基础。
先写一个hello world的程序:
#include <stdio.h>
int main()
{
printf("Hello, World!\n");
return 0;
}
2 数据类型
数据类型 | 32为下字节数 | 64位下字节数 | 打印格式 | |
char | 字符数据类型 | 1字节 | 1字节 | %c或%s |
short | 短整型 | 2字节 | 2字节 | %d |
int | 整形 | 4字节 | 4字节 | %d |
long | 长整型 | 4字节 | 4字节(Linux系统下为8字节) | %ld |
long long | 长长整形 | 8字节 | 8字节 | %lld |
float | 单精度浮点型 | 4字节 | 4字节 | %f |
double | 双精度浮点型 | 8字节 | 8字节 | %lf |
注意:由于long类型在Windows系统和Linux系统中,字节数不同,因此考虑到程序的可移植性,应避免使用long类型。
计算机存储单位之间的换算:
3 变量
3.1 变量的定义
#include <stdio.h>
int main()
{
// 定义整型变量
int a; // 声明变量
a = 10; // 初始化变量
// 定义浮点型变量并初始化
float b = 5.5;
// 定义字符型变量
char c = 'A';
// 输出变量的值
printf("a = %d\n", a);
printf("b = %.2f\n", b);
printf("c = %c\n", c);
return 0;
}
3.2 变量的分类
在C语言中,变量可以根据其作用域和生命周期分为两大类:局部变量和全局变量。
局部变量:
- 定义:局部变量是在函数内部定义的变量。
- 作用域:仅在定义它的函数或代码块内可见。
- 生命周期:当函数执行结束后,局部变量的存储空间会被释放。
- 初始化:局部变量在声明时未被初始化的情况下,其值是未定义的。
全局变量:
- 定义:全局变量是在所有函数外部定义的变量。
- 作用域:在整个程序中可见,所有函数都可以访问。
- 生命周期:程序运行期间一直存在,直到程序结束。
- 初始化:全局变量会自动初始化为零(对于基本数据类型)。
代码示例:全局变量和局部变量的使用
#include <stdio.h>
int global = 2019; // 全局变量
int main()
{
int local = 2018; // 局部变量
// 下面定义的 global 会隐藏全局变量
int global = 2020; // 局部变量
printf("global = %d\n", global); // 输出局部变量 global 的值
return 0;
}
总结:当局部变量和全局变量同名的时候,局部变量优先使用。
3.3 变量的作用域和生命周期
作用域:作用域(scope)是程序设计中的一个概念,指的是一个程序中变量的可用范围。具体来说,它限制了一个名称的可用性的代码范围。
- 局部变量的作用域是变量所在的局部范围。
- 全局变量的作用域是整个程序。
生命周期:生命周期指的是变量的创建到销毁之间的一个时间段。
- 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
- 全局变量的生命周期是:整个程序的生命周期。
4 常量
4.1 字面常量
字面常量(literal constant)是指在程序中直接写出的固定值,表示特定的数据类型,而不需要任何计算或变量的引用。字面常量的值在代码中是明确的,并且在程序执行期间不会改变。
字面常量可以分为几种类型:
- 整数常量:如 10、-5、0
- 浮点常量:如 3.14、-0.001、2.0
- 字符常量:如 'A'、'z'
- 字符串常量:如 "Hello, world!"、"123"
- 布尔常量:如 true、false
4.2 const修饰的常变量
在编程中,const
修饰符用于定义常量变量,这些变量在初始化后不能被修改。const
常量的作用是提高代码的可读性和安全性,防止意外修改。
特点:
- 不可修改:一旦被初始化,const 修饰的变量的值不能被改变。
- 作用域:const常量的作用域与普通变量相同,可以是全局或局部的。
- 类型安全: 常量具有明确的数据类型,编译器会在编译时进行类型检查。
const int maxUsers = 100;
// maxUsers = 200; // 错误,不能修改
4.3 #define定义的标识符常量
#define 指令用于定义预处理器宏,可以创建标识符常量。
与 const 常量不同,#define 是在编译前进行文本替换的,通常用于定义常量值、表达式或代码片段。
特点:
- 文本替换:#define 定义的标识符在预处理阶段被替换为其定义的值。
- 没有类型:#define 不会进行类型检查,因为它只是简单的文本替换。
- 作用域:#define 的作用域是从被定义的位置到文件的结束,或者直到被 #undef 取消定义。
#define PI 3.14
#define MAX_USERS 100
#include <stdio.h>
int main()
{
printf("PI is: %f\n", PI);
printf("Max users: %d\n", MAX_USERS);
return 0;
}
注意:因为没有类型检查,使用 #define 时要注意避免潜在的错误,例如在表达式中使用时可能会引发意外的行为。
4.4 枚举常量
枚举常量(enum constants)是一种在编程中用于定义一组命名整型常量的类型。枚举提供了一种更具可读性和可维护性的方式来处理一组相关值。
特点:
- 命名常量:枚举常量具有名称,便于理解和使用。
- 整型值:枚举常量通常被赋予整型值,默认从 0 开始递增,当然也可以手动指定值。
- 类型安全:枚举提供了一种类型安全的方式来处理常量,避免了魔法数字的使用。
#include <stdio.h>
enum Color
{
RED, // 默认值为 0
GREEN, // 默认值为 1
BLUE // 默认值为 2
};
int main()
{
enum Color myColor = GREEN;
printf("My color is: %d\n", myColor); // 输出 1
return 0;
}
5 字符串
字符串:由双引号(Double Quote)引起来的一串字符。
例如:
"hello bit.\n"
注意:字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串内容。
#include <stdio.h>
//下面代码,打印结果是什么?为什么?(强调 '\0' 的重要性)
int main()
{
char arr1[] = "ppph";
char arr2[] = {'p', 'p', 'p', 'h'};
char arr3[] = {'p', 'p', 'p', 'h', '\0'};
printf("%s\n", arr1);
printf("%s\n", arr2);
printf("%s\n", arr3);
return 0;
}
打印结果:
- arr1: 输出 ppph,使用字符串字面值,自动添加 \0 结束符。
- arr2: 输出未定义行为,没有 \0 结束符,printf 无法确定字符串结束,可能打印出随机内容或导致错误。
- arr3: 输出 ppph,明确包含 \0 结束符,正确表示字符串。
6 转义字符
转义字符(Escape Characters)是在字符串中表示特殊字符的方式,通常以反斜杠(\
)开头。它们用于表示无法直接输入的字符或具有特殊意义的字符。
转义字符 | 释义 |
\? | 在书写连续多个问号时使用,防止被解析成三字母词 |
\'与\''与\\ | 为了正确输出’与"与\ |
\n | 换行 |
\r | 回车 |
\t | 水平制表符(效果同TAB键) |
\d与\dd与\ddd | d表示8进制数字(注:ASCII表最大数字为127) |
\xd与\xdd | d表示16进制数字(注:ASCII表最大数字为127) |
\a | 警告字符,蜂鸣 |
\b | 退格符 |
\f | 进纸符 |
\v | 垂直制表符 |
#include <stdio.h>
int main()
{
printf("Hello, World!\n"); // 输出后换行
printf("This is a tab:\tHello!\n"); // 输出一个制表符
printf("Quotes: \'Single\' and \"Double\"\n"); // 输出引号
printf("%d\n", strlen("c:\test\628\test.c")); //\t与\62与\t会被转义,最终打印14
return 0;
}
7 注释
- 代码中有不需要的代码可以直接删除,也可以注释掉;
- 代码中有些代码比较难懂,可以加一下注释文字。
注释有两种风格:
- C语言风格的注释/*xxxxxx*/,不能嵌套注释
- C++风格的注释/xxxxxxXX,可以注释一行也可以注释多行
#include <stdio.h>
int Add(int x, int y)
{
return x + y;
}
/* C语言风格注释
int Sub(int x, int y)
{
return x - y;
}
*/
int main()
{
// C++注释风格
// int a = 10;
// 调用 Add 函数,完成加法
printf("%d\n", Add(1, 2));
return 0;
}