在Linux环境下进行C语言开发,我们需要准备以下核心工具链:
安装命令(以Ubuntu为例):
bash复制sudo apt update
sudo apt install build-essential gdb
这个命令会安装:
让我们创建一个经典的Hello World程序来验证环境:
bash复制vim hello.c
c复制#include <stdio.h>
int main() {
printf("Hello, Linux C Programming!\n");
return 0;
}
保存并退出vim(按ESC,然后输入:wq)
编译程序:
bash复制gcc hello.c -o hello
bash复制./hello
C语言从源代码到可执行文件经历了四个主要阶段:
预处理:处理宏定义、头文件包含等
bash复制gcc -E hello.c -o hello.i
编译:将预处理后的代码转换为汇编代码
bash复制gcc -S hello.i -o hello.s
汇编:将汇编代码转换为机器码(目标文件)
bash复制gcc -c hello.s -o hello.o
链接:将目标文件与库文件链接生成可执行文件
bash复制gcc hello.o -o hello
C语言提供了丰富的数据类型来满足不同编程需求:
| 类型 | 说明 | 大小(字节) | 范围 |
|---|---|---|---|
| char | 字符 | 1 | -128~127 |
| unsigned char | 无符号字符 | 1 | 0~255 |
| short | 短整型 | 2 | -32768~32767 |
| int | 整型 | 4 | -2147483648~2147483647 |
| long | 长整型 | 4/8 | 系统相关 |
| float | 单精度浮点 | 4 | 约6-7位有效数字 |
| double | 双精度浮点 | 8 | 约15-16位有效数字 |
变量声明示例:
c复制int age = 25;
float salary = 8500.50;
char grade = 'A';
C语言提供了丰富的运算符:
运算符优先级表(从高到低):
c复制// if语句
if (condition) {
// 代码块
} else if (another_condition) {
// 代码块
} else {
// 代码块
}
// switch语句
switch (expression) {
case constant1:
// 代码块
break;
case constant2:
// 代码块
break;
default:
// 代码块
}
c复制// while循环
while (condition) {
// 代码块
}
// do-while循环
do {
// 代码块
} while (condition);
// for循环
for (init; condition; increment) {
// 代码块
}
Linux下文件操作是系统编程的基础,常用函数:
c复制#include <stdio.h>
FILE *fopen(const char *pathname, const char *mode);
int fclose(FILE *stream);
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
int fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream);
文件操作示例:
c复制#include <stdio.h>
int main() {
FILE *fp;
char buffer[100];
// 写入文件
fp = fopen("test.txt", "w");
if (fp == NULL) {
perror("打开文件失败");
return 1;
}
fputs("这是写入的测试内容\n", fp);
fclose(fp);
// 读取文件
fp = fopen("test.txt", "r");
if (fp == NULL) {
perror("打开文件失败");
return 1;
}
while (fgets(buffer, 100, fp) != NULL) {
printf("%s", buffer);
}
fclose(fp);
return 0;
}
Linux提供了丰富的进程控制函数:
c复制#include <unistd.h>
#include <sys/types.h>
pid_t fork(void); // 创建子进程
int execve(const char *pathname, char *const argv[], char *const envp[]); // 执行新程序
pid_t wait(int *wstatus); // 等待子进程结束
进程创建示例:
c复制#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
pid_t pid = fork();
if (pid < 0) {
perror("fork失败");
return 1;
} else if (pid == 0) {
// 子进程
printf("这是子进程,PID=%d\n", getpid());
sleep(2);
printf("子进程结束\n");
} else {
// 父进程
printf("这是父进程,PID=%d,子进程PID=%d\n", getpid(), pid);
wait(NULL); // 等待子进程结束
printf("父进程结束\n");
}
return 0;
}
指针是C语言的核心概念,理解指针对于Linux系统编程至关重要。
c复制#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr;
int n = 5;
// 动态内存分配
ptr = (int *)malloc(n * sizeof(int));
if (ptr == NULL) {
perror("内存分配失败");
return 1;
}
// 使用分配的内存
for (int i = 0; i < n; i++) {
ptr[i] = i * 10;
}
// 打印内容
for (int i = 0; i < n; i++) {
printf("%d ", ptr[i]);
}
printf("\n");
// 释放内存
free(ptr);
return 0;
}
Makefile可以自动化编译过程,提高开发效率:
makefile复制CC = gcc
CFLAGS = -Wall -g
TARGET = myprogram
SRCS = main.c utils.c
OBJS = $(SRCS:.c=.o)
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $@ $^
%.o: %.c
$(CC) $(CFLAGS) -c $<
clean:
rm -f $(OBJS) $(TARGET)
使用GDB调试C程序的基本步骤:
bash复制gcc -g program.c -o program
bash复制gdb ./program
常用GDB命令:
break:设置断点run:运行程序next:单步执行(不进入函数)step:单步执行(进入函数)print:打印变量值backtrace:查看调用栈continue:继续执行quit:退出GDB让我们综合运用所学知识,开发一个简单的文件加密工具:
c复制#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define KEY 0x55 // 简单的异或加密密钥
void encrypt_file(const char *input_file, const char *output_file) {
FILE *fin, *fout;
int ch;
fin = fopen(input_file, "rb");
if (fin == NULL) {
perror("无法打开输入文件");
exit(EXIT_FAILURE);
}
fout = fopen(output_file, "wb");
if (fout == NULL) {
perror("无法创建输出文件");
fclose(fin);
exit(EXIT_FAILURE);
}
while ((ch = fgetc(fin)) != EOF) {
fputc(ch ^ KEY, fout); // 简单的异或加密
}
fclose(fin);
fclose(fout);
}
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("用法: %s 输入文件 输出文件\n", argv[0]);
return EXIT_FAILURE;
}
encrypt_file(argv[1], argv[2]);
printf("文件加密/解密完成!\n");
return EXIT_SUCCESS;
}
编译并运行:
bash复制gcc -Wall -o encrypt encrypt.c
./encrypt input.txt output.enc
这个简单的加密工具使用异或运算对文件进行加密,同样的程序也可以用于解密,因为异或运算的特性是:(A ^ KEY) ^ KEY = A。
GCC提供了多种优化选项:
-O0:不优化(默认)-O1:基本优化-O2:推荐优化级别-O3:激进优化-Os:优化代码大小示例:
bash复制gcc -O2 -o program program.c
inline关键字register关键字提示编译器优化示例:
c复制// 未优化的代码
for (int i = 0; i < strlen(s); i++) {
// ...
}
// 优化后的代码
int len = strlen(s);
for (int i = 0; i < len; i++) {
// ...
}
段错误是Linux C编程中最常见的问题之一,通常由以下原因引起:
调试方法:
valgrind工具检测内存问题内存泄漏是指程序未能释放不再使用的内存,长期运行会导致内存耗尽。
检测工具:
bash复制valgrind --leak-check=full ./program
预防措施:
malloc都要有对应的freeLinux下多线程编程常见问题:
解决方案:
掌握了C语言基础后,可以继续深入学习以下方向:
推荐书籍:
推荐使用Vim作为主要编辑器,配置建议:
bash复制curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
vim复制syntax on
set number
set tabstop=4
set shiftwidth=4
set expandtab
set autoindent
set cursorline
call plug#begin('~/.vim/plugged')
Plug 'vim-syntastic/syntastic'
Plug 'preservim/nerdtree'
Plug 'vim-airline/vim-airline'
call plug#end()
除了GDB,还可以使用以下工具:
Valgrind:内存调试工具
bash复制valgrind --tool=memcheck ./program
strace:系统调用跟踪
bash复制strace ./program
ltrace:库函数调用跟踪
bash复制ltrace ./program
良好的编码习惯能提高代码质量和可维护性:
命名规范:
student_countMAX_SIZEcalculate_average注释规则:
代码组织:
错误处理:
示例规范的代码片段:
c复制/*
* 文件:calculator.c
* 作者:张三
* 描述:简单的四则运算实现
*/
#include <stdio.h>
#include <stdlib.h>
#define MAX_INPUT_LEN 100
/**
* 计算两个数的和
* @param a 第一个操作数
* @param b 第二个操作数
* @return 两个数的和
*/
int add(int a, int b) {
return a + b;
}
int main() {
int num1, num2;
char input[MAX_INPUT_LEN];
printf("请输入两个整数,用空格分隔: ");
if (fgets(input, sizeof(input), stdin) == NULL) {
fprintf(stderr, "读取输入失败\n");
return EXIT_FAILURE;
}
if (sscanf(input, "%d %d", &num1, &num2) != 2) {
fprintf(stderr, "输入格式错误\n");
return EXIT_FAILURE;
}
printf("结果: %d\n", add(num1, num2));
return EXIT_SUCCESS;
}