目录
一、C语言概述
C语言是一种广泛使用的计算机编程语言,由Dennis Ritchie于1972年在贝尔实验室开发,主要用于Unix操作系统的开发。C语言具有高度的可移植性,是许多现代编程语言(如C++、Java、C#等)的基础。
C语言的语法简单,易于学习。它提供了基础的编程构造,如变量、数据类型、运算符、控制语句等。同时,C语言还允许直接访问物理地址和底层硬件资源,这使得它非常适合系统编程和嵌入式系统开发。
C语言编写的程序可以在多种计算机平台上运行,只要有相应的编译器。此外,C语言还提供了一个丰富的标准库,包含了一系列的函数,可以进行输入输出操作、数学计算、字符串处理等。
C语言的灵活性非常高,为开发者提供了大量的控制能力,允许直接操作内存、使用指针等。这使得C语言编写的程序通常运行效率很高,因为它接近硬件层,可以优化资源使用。
C语言的应用领域非常广泛,包括系统软件、应用软件、嵌入式系统和网络编程等。C语言的影响力非常深远,它不仅影响了后来的编程语言的发展,也成为了计算机科学教育中重要的组成部分。许多现代编程语言在某种程度上都受到了C语言的影响。
二、C语言语法
下面是C语言的一些主要语法特性,但并不代表全部。C语言的标准随着时间的推移而发展
2.1 基本数据类型:
- 整型(int, short, long, long long)
- 浮点型(float, double, long double)
- 字符型(char)
- 布尔型(_Bool, bool)(C99标准)
2.2 变量和常量:
- 变量的声明和初始化
- 常量的声明(如字面量:整数、浮点数、字符、字符串等)
示例:
// 整型变量
int x; // 声明整型变量x
int y = 10; // 声明并初始化整型变量y,值为10
// 浮点型变量
float pi = 3.14159; // 声明并初始化浮点型变量pi
// 字符型变量
char ch = 'A'; // 声明并初始化字符型变量ch,值为'A'
// 字符串常量
// 在C中,字符串常量是用双引号括起来的字符序列
char *str = "Hello, World!"; // 声明一个指向字符串常量的指针变量str
// 布尔型变量
_Bool flag = TRUE; // 在C99标准中,可以使用_Bool类型声明布尔变量,TRUE和FALSE是预定义的宏
// 或者使用int类型
int isTrue = 1; // 布尔值通常用0表示假,非0表示真,在C中布尔值通常表现为整型
2.3 运算符:
- 算术运算符(+, -, *, /, %)
- 关系运算符(==, !=, <, >, <=, >=)
- 逻辑运算符(&&, ||, !)
- 位运算符(&, |, ^, <<, >>)
- 赋值运算符(=, +=, -=, *=, /=, %=)
- 扩展赋值运算符(+=, -=, *=, /=, %=)
示例:
// 算术运算符
int a = 10;
int b = 20;
int sum = a + b; // 加法
int difference = a - b; // 减法
int product = a * b; // 乘法
double quotient = a / b; // 浮点除法
int remainder = a % b; // 取模
// 关系运算符
int x = 10;
int y = 20;
int equal = x == y; // 等于
int notEqual = x != y; // 不等于
int lessThan = x < y; // 小于
int greaterThan = x > y; // 大于
int lessThanOrEqual = x <= y; // 小于或等于
int greaterThanOrEqual = x >= y; // 大于或等于
// 逻辑运算符
int trueValue = 1;
int falseValue = 0;
int result1 = trueValue && falseValue; // 逻辑与(AND)
int result2 = trueValue || falseValue; // 逻辑或(OR)
int result3 = !trueValue; // 逻辑非(NOT)
// 位运算符
int bitwiseAnd = 10 & 12; // 位与
int bitwiseOr = 10 | 12; // 位或
int bitwiseXor = 10 ^ 12; // 位异或
int leftShift = 10 << 2; // 左移
int rightShift = 10 >> 2; // 右移
// 赋值运算符
int zero = 0;
int increment = zero++; // 先使用后增加,初始值为0
int postIncrement = ++zero; // 先增加后使用,初始值为1
int decrement = zero--; // 先使用后减少,初始值为1
int postDecrement = --zero; // 先减少后使用,初始值为0
// 扩展赋值运算符
int addAndAssign = zero += 5; // 赋值加法
int subtractAndAssign = zero -= 3; // 赋值减法
int multiplyAndAssign = zero *= 2; // 赋值乘法
int divideAndAssign = zero /= 4; // 赋值除法
int modulusAndAssign = zero %= 3; // 赋值取模
2.4 控制结构:
- 条件语句(if, if-else, switch)
- 循环语句(for, while, do-while)
- 跳转语句(goto, continue, break)
示例:
// 条件语句
int age = 25;
if (age >= 18) {
printf("You are eligible to vote.\n");
} else {
printf("You are not eligible to vote.\n");
}
// if-else语句
int score = 85;
if (score >= 90) {
printf("Grade: A\n");
} else if (score >= 80) {
printf("Grade: B\n");
} else if (score >= 70) {
printf("Grade: C\n");
} else {
printf("Grade: F\n");
}
// switch语句
char grade = 'B';
switch (grade) {
case 'A':
printf("Excellent!\n");
break;
case 'B':
printf("Good!\n");
break;
case 'C':
printf("Fair!\n");
break;
case 'D':
printf("Poor!\n");
break;
case 'F':
printf("Failing...\n");
break;
default:
printf("Invalid grade.\n");
}
// 循环语句
// for循环
for (int i = 0; i < 5; i++) {
printf("%d\n", i);
}
// while循环
int count = 0;
while (count < 5) {
printf("%d\n", count);
count++;
}
// do-while循环
int j = 0;
do {
printf("%d\n", j);
j++;
} while (j < 5);
// 跳转语句
// goto语句
// 通常不推荐使用goto语句,因为它会打断程序的流程
// 但是在某些情况下,如需要从多个层面上退出循环时,可能会用到
label:
for (int k = 0; k < 5; k++) {
if (k == 2) {
goto label; // 跳转到label标签,通常用于跳出多重循环
}
printf("%d\n", k);
}
// continue语句
for (int m = 0; m < 5; m++) {
if (m == 2) {
continue; // 跳过当前循环的剩余部分,继续下一次循环
}
printf("%d\n", m);
}
// break语句
for (int n = 0; n < 5; n++) {
if (n == 2) {
break; // 终止当前循环
}
printf("%d\n", n);
}
2.5 函数:
- 函数的声明和定义
- 函数的参数传递(值传递、指针传递、引用传递)
- 函数的返回值
示例:
#include <stdio.h>
// 函数的声明
void printMessage(); // 声明一个没有参数和返回值的函数
int add(int a, int b); // 声明一个有两个整型参数和一个整型返回值的函数
void changeValue(int num); // 声明一个有一个整型参数的函数,参数值传递
void increment(int *ptr); // 声明一个有一个整型指针参数的函数,指针传递
void swap(int *x, int *y); // 声明一个有两个整型指针参数的函数,引用传递
int sum(int x, int y); // 声明一个有两个整型参数和一个整型返回值的函数
void greet(const char *name); // 声明一个接受const char*参数的函数
// 函数的定义
void printMessage() {
printf("Hello, World!\n");
}
int add(int a, int b) {
return a + b;
}
void changeValue(int num) {
num = 20; // 参数的值在这里被改变,但不会影响调用者的值
}
void increment(int *ptr) {
(*ptr)++; // 通过指针修改指向的值
}
void swap(int *x, int *y) {
int temp = *x;
*x = *y;
*y = temp;
}
int sum(int x, int y) {
return x + y;
}
void greet(const char *name) {
printf("Hello, %s!\n", name);
}
// 函数的调用
int main() {
printMessage(); // 调用printMessage函数
int result = add(5, 10); // 调用add函数并存储返回值
printf("The sum is %d\n", result); // 输出结果为15
int value = 10;
changeValue(value); // 调用函数,value的值被改变为20
printf("Value after function call: %d\n", value); // 输出仍然是20,因为值传递是单向的
int num = 10;
increment(&num); // 通过指针传递num的地址
printf("Value after function call: %d\n", num); // 输出变为11
int a = 10, b = 20;
swap(&a, &b); // 调用函数,a和b的值被交换
printf("a: %d, b: %d\n", a, b); // 输出变为20和10
greet("Alice"); // 调用greet函数
return 0;
}
2.6 指针和内存管理:
- 指针的声明和初始化
- 指针的算术操作(增加、减少)
- 指针与数组
- 动态内存分配(malloc, calloc, realloc, free)
示例:
#include <stdio.h>
#include <stdlib.h>
int main() {
// 指针的声明和初始化
int num = 10;
int *ptr = # // 声明一个指向整型的指针,并初始化为num的地址
// 指针的算术操作
// 指针可以增加或减少其指向类型的尺寸
ptr++; // ptr现在指向num之后的下一个整型变量
ptr--; // ptr回到num的地址
// 指针与数组
int arr[5] = {1, 2, 3, 4, 5};
int *ptr_to_arr = arr; // 声明一个指向数组的指针
// 循环通过指针访问数组元素
for (int i = 0; i < 5; i++) {
printf("Element %d: %d\n", i, *(ptr_to_arr + i));
}
// 动态内存分配
// 使用malloc分配一个整型数据的内存
int *dynamic_ptr = (int*)malloc(sizeof(int));
if (dynamic_ptr == NULL) {
printf("Memory allocation failed.\n");
return 1;
}
// 分配并初始化一个整型数组
int *dynamic_array = (int*)malloc(10 * sizeof(int));
if (dynamic_array == NULL) {
printf("Memory allocation failed.\n");
return 1;
}
for (int i = 0; i < 10; i++) {
dynamic_array[i] = i;
}
// 使用动态分配的内存
printf("Dynamic array element: %d\n", dynamic_array[4]);
// 释放动态分配的内存
free(dynamic_ptr);
free(dynamic_array);
return 0;
}
2.7 数组和字符串:
- 一维、多维数组的声明和访问
- 字符串的处理(strlen, strcpy, strcat等)
- 结构体和联合体:
- 结构体的声明和定义
- 联合体的声明和定义
- 结构体和联合体的初始化
示例:
#include <stdio.h>
#include <string.h>
typedef struct Person {
char name[50];
int age;
float height;
} Person;
typedef union {
int integer;
float floating_point;
char string[20];
} DataUnion;
int main() {
// 一维数组的声明和访问
int arr[5] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; i++) {
printf("arr[%d] = %d\n", i, arr[i]);
}
// 多维数组的声明和访问
int multi_arr[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("multi_arr[%d][%d] = %d\n", i, j, multi_arr[i][j]);
}
}
// 字符串的处理
char str1[] = "Hello";
char str2[] = "World";
char str3[20];
strcpy(str3, str1); // 复制字符串
strcat(str3, str2); // 连接字符串
printf("str3 = %s\n", str3);
printf("Length of str3 = %d\n", strlen(str3));
// 结构体的声明和定义
Person person1;
strcpy(person1.name, "John");
person1.age = 30;
person1.height = 1.8f;
printf("Name: %s\nAge: %d\nHeight: %.2f\n", person1.name, person1.age, person1.height);
// 联合体的声明和定义
DataUnion data;
data.integer = 42;
printf("Integer: %d\n", data.integer);
data.floating_point = 3.14f;
printf("Floating-point: %f\n", data.floating_point);
strcpy(data.string, "Test");
printf("String: %s\n", data.string);
// 结构体和联合体的初始化
Person person2 = {"Jane", 25, 1.65f}; // 初始化结构体
DataUnion data2 = {.integer = 10}; // 初始化联合体,只初始化整型部分
return 0;
}
2.8 枚举:
- 枚举类型的声明和定义
示例:
#include <stdio.h>
// 声明一个枚举类型WeekDay
enum WeekDay {
MONDAY, // 周一
TUESDAY, // 周二
WEDNESDAY, // 周三
THURSDAY, // 周四
FRIDAY, // 周五
SATURDAY, // 周六
SUNDAY // 周日
};
int main() {
// 声明一个枚举变量并赋值
enum WeekDay today;
today = TUESDAY;
// 打印枚举变量的值
printf("Today is %d, which is %s.\n", today, today == MONDAY ? "Monday" :
today == TUESDAY ? "Tuesday" :
today == WEDNESDAY ? "Wednesday" :
today == THURSDAY ? "Thursday" :
today == FRIDAY ? "Friday" :
today == SATURDAY ? "Saturday" : "Sunday");
return 0;
}
2.9 文件操作:
- 文件的打开和关闭(fopen, fclose)
- 文件的读写(fread, fwrite, fgets, fputs等)
- 文件的定位(fseek, ftell, rewind)
示例:
#include <stdio.h>
#include <stdlib.h>
int main() {
// 文件的打开和关闭
FILE *filePtr;
filePtr = fopen("example.txt", "r+"); // 打开文件用于读取和写入
if (filePtr == NULL) {
perror("Error opening file");
return EXIT_FAILURE;
}
// 文件的读写
char buffer[100];
fgets(buffer, sizeof(buffer), filePtr); // 读取一行数据
printf("Read from file: %s\n", buffer);
fputs("Hello, World!", filePtr); // 向文件写入数据
// 文件的定位
long fileSize;
fileSize = ftell(filePtr); // 获取当前文件指针的位置
printf("File size: %ld\n", fileSize);
fseek(filePtr, 0, SEEK_SET); // 重新定位文件指针到文件开始
fgets(buffer, sizeof(buffer), filePtr); // 再次读取一行数据
printf("Read again: %s\n", buffer);
// 文件的关闭
fclose(filePtr); // 关闭文件
return 0;
}
2.10 预处理器指令:
- 宏定义(#define)
- 文件包含(#include)
- 条件编译(#ifdef, #ifndef, #if defined, #endif)
示例:
宏定义(#define):
#include <stdio.h>
#define PI 3.14159
int main(){
printf("The value of PI is %f\n", PI);
}
文件包含(#include):
#include <stdio.h>
// 这会包含标准输入输出头文件的内容
条件编译(#ifdef, #ifndef, #if defined, #endif):
#ifdef DEBUG
// 如果定义了DEBUG宏,则编译此代码块
printf("Debugging is enabled.\n");
#endif
#ifndef RELEASE
// 如果未定义RELEASE宏,则编译此代码块
printf("This is not the release version.\n");
#endif
#if defined(WIN32)
// 如果定义了WIN32宏,则编译此代码块(针对Windows平台)
printf("Running on Windows.\n");
#elif defined(LINUX)
// 如果定义了LINUX宏,则编译此代码块(针对Linux平台)
printf("Running on Linux.\n");
#else
// 如果没有定义WIN32或LINUX宏,则编译此代码块
printf("Running on an unknown platform.\n");
#endif
// #endif 用于结束条件编译块
2.11 标准库:
- 输入输出库(stdio.h)
- 字符串处理库(string.h)
- 数学库(math.h)
- 时间库(time.h)
示例:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <time.h>
int main() {
// 输入输出库 stdio.h
printf("Enter your name: ");
char name[100];
fgets(name, sizeof(name), stdin); // 读取输入直到换行符
printf("Hello, %s!\n", name); // 输出输入的名字
// 字符串处理库 string.h
char str[] = "Hello, World!";
printf("Length of str: %d\n", strlen(str)); // 输出字符串长度
printf("Concatenated string: %s\n", strcat(str, " Welcome!")); // 连接字符串
// 数学库 math.h
double num = 9.0;
printf("Square root of %f is %f\n", num, sqrt(num)); // 输出数的平方根
printf("Pi is approximately %f\n", M_PI); // 输出圆周率的值
// 时间库 time.h
time_t now;
struct tm *local;
time(&now); // 获取当前时间
local = localtime(&now); // 将时间转换为本地时间
printf("Current local time: %s", asctime(local)); // 输出本地时间
return 0;
}