Clanguageadvanced主题tutorial

LearningClanguage advanced features, including预processing指令, 位运算, many fileprogramming, C标准library and performanceoptimizationtechniques

返回tutoriallist

1. 预processing指令

1.1 what is 预processing指令

预processing指令 is in 编译之 before 由预processing器processing 指令, 它们以井号 (#) 开头. 预processing指令用于宏定义, 条件编译, filepackage含etc.operation.

1.2 common 预processing指令

  • #define: 定义宏
  • #include: package含头file
  • #ifdef, #ifndef, #endif: 条件编译
  • #if, #elif, #else: 条件编译
  • #undef: 取消宏定义
  • #pragma: 编译器specific 指令
  • #error: 产生errorinformation
  • #warning: 产生warninginformation

1.3 宏定义

宏定义用于creation符号常量 or 宏function, improvingcode readable 性 and 可maintenance性.

// 定义符号常量
#define PI 3.14159
#define MAX_SIZE 100

// 定义宏function
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define SQUARE(x) ((x) * (x))

int main() {
    int a = 10, b = 20;
    printf("PI = %f\n", PI);
    printf("MIN(%d, %d) = %d\n", a, b, MIN(a, b));
    printf("MAX(%d, %d) = %d\n", a, b, MAX(a, b));
    printf("SQUARE(%d) = %d\n", a, SQUARE(a));
    return 0;
}

1.4 条件编译

条件编译用于根据条件选择性地编译code, 常用于跨平台Development and debug.

#include <stdio.h>

#define DEBUG 1
#define PLATFORM "Windows"

int main() {
    printf("Hello, World!\n");
    
#ifdef DEBUG
    printf("Debug mode is enabled\n");
#endif
    
#ifndef NDEBUG
    printf("Not in release mode\n");
#endif
    
#if defined(PLATFORM) && PLATFORM == "Windows"
    printf("Running on Windows\n");
#elif defined(PLATFORM) && PLATFORM == "Linux"
    printf("Running on Linux\n");
#else
    printf("Running on unknown platform\n");
#endif
    
    return 0;
}

1.5 filepackage含

filepackage含用于将otherfile in 容package含 to 当 before filein, 通常用于package含头file.

// package含标准library头file
#include <stdio.h>
#include <stdlib.h>

// package含user定义 头file
#include "myheader.h"

int main() {
    // code
    return 0;
}

2. 位运算

2.1 位运算符

位运算符用于 for 整数 二进制位foroperation, including按位 and , 按位 or , 按位异 or , 按位取反, left 移 and right 移etc..

运算符 describes example
& 按位 and 10 & 3 = 2 (1010 & 0011 = 0010)
| 按位 or 10 | 3 = 11 (1010 | 0011 = 1011)
^ 按位异 or 10 ^ 3 = 9 (1010 ^ 0011 = 1001)
~ 按位取反 ~10 = -11 (按位取反1010得 to 0101, 再按补码规则得 to -11)
<< left 移 10 << 2 = 40 (1010 << 2 = 101000)
>> right 移 10 >> 2 = 2 (1010 >> 2 = 10)

2.2 位运算 application

位运算 in 以 under 场景in非常 has 用:

  • 位掩码: 用于标志位operation
  • 位字段: 用于节省memory
  • 位operationoptimization: improvingcodeefficiency
  • encryption and 哈希algorithms: using位运算fordataprocessing
  • 硬件programming: and 硬件寄存器for交互
// 位掩码example
#include <stdio.h>

// 定义标志位
#define FLAG_A 0x01  // 0001
#define FLAG_B 0x02  // 0010
#define FLAG_C 0x04  // 0100
#define FLAG_D 0x08  // 1000

int main() {
    int flags = 0;
    
    // 设置标志位
    flags |= FLAG_A;
    flags |= FLAG_C;
    
    printf("Flags: 0x%x\n", flags);  // 输出: Flags: 0x5
    
    // check标志位
    if (flags & FLAG_A) {
        printf("Flag A is set\n");
    }
    
    if (flags & FLAG_B) {
        printf("Flag B is set\n");
    } else {
        printf("Flag B is not set\n");
    }
    
    // 清除标志位
    flags &= ~FLAG_A;
    printf("Flags after clearing A: 0x%x\n", flags);  // 输出: Flags after clearing A: 0x4
    
    return 0;
}

3. many fileprogramming

3.1 for whatusing many fileprogramming

in big 型projectin, 将code分散 to many 个filein可以improvingcode 可maintenance性, readable 性 and reusability. many fileprogramming 优点including:

  • module化: 将functions相关 code组织 in 一起
  • 可maintenance性: 便于modify and debugspecificfunctions
  • reusability: 可以 in many 个projectinusing相同 module
  • 编译速度: 只需要重 new 编译modify过 file
  • 团队协作: many 个Development者可以同时工作 in 不同 file on

3.2 many fileprogramming basicstructure

一个典型 Clanguageproject通常package含以 under class型 file:

  • .h file (头file) : package含function声明, 宏定义, class型定义etc.
  • .c file (sourcesfile) : package含functionimplementation

3.2.1 头file

// mymath.h
#ifndef MYMATH_H
#define MYMATH_H

// function声明
double add(double a, double b);
double subtract(double a, double b);
double multiply(double a, double b);
double divide(double a, double b);

#endif  // MYMATH_H

3.2.2 sourcesfile

// mymath.c
#include "mymath.h"

// functionimplementation
double add(double a, double b) {
    return a + b;
}

double subtract(double a, double b) {
    return a - b;
}

double multiply(double a, double b) {
    return a * b;
}

double divide(double a, double b) {
    if (b != 0) {
        return a / b;
    }
    return 0;  // 简化processing, practical应processing除零error
}

3.2.3 主file

// main.c
#include <stdio.h>
#include "mymath.h"

int main() {
    double a = 10.0, b = 5.0;
    
    printf("%f + %f = %f\n", a, b, add(a, b));
    printf("%f - %f = %f\n", a, b, subtract(a, b));
    printf("%f * %f = %f\n", a, b, multiply(a, b));
    printf("%f / %f = %f\n", a, b, divide(a, b));
    
    return 0;
}

3.3 编译 and 链接 many fileproject

for 于 many fileproject, 可以using以 under commands编译 and 链接:

// 分别编译每个sourcesfile
gcc -c main.c
gcc -c mymath.c

// 链接目标file
gcc main.o mymath.o -o program

//  or 者一步completion编译 and 链接
gcc main.c mymath.c -o program

4. C标准library

4.1 常用 标准library头file

  • <stdio.h>: 标准输入输出function
  • <stdlib.h>: commontoolfunction (memory分配, 随机数etc.)
  • <string.h>: stringprocessingfunction
  • <math.h>: 数学function
  • <time.h>: 时间 and 日期function
  • <ctype.h>: 字符processingfunction
  • <stdint.h>: 整数class型定义
  • <stdbool.h>: booleanclass型定义
  • <stdarg.h>: 可变parameterprocessing
  • <assert.h>: assertionfunction

4.2 标准libraryfunctionexample

// 标准libraryfunctionexample
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <ctype.h>

int main() {
    // stdio.h
    printf("Hello, World!\n");
    
    // stdlib.h
    int *ptr = (int *)malloc(5 * sizeof(int));
    if (ptr != NULL) {
        for (int i = 0; i < 5; i++) {
            ptr[i] = i + 1;
        }
        free(ptr);
    }
    
    // string.h
    char str1[20] = "Hello";
    char str2[] = " World";
    strcat(str1, str2);
    printf("strcat: %s\n", str1);
    
    // math.h
    double x = 2.0;
    printf("sqrt(%.2f) = %.2f\n", x, sqrt(x));
    printf("pow(%.2f, 3) = %.2f\n", x, pow(x, 3));
    
    // time.h
    time_t now = time(NULL);
    struct tm *tm_now = localtime(&now);
    printf("Current time: %02d:%02d:%02d\n", 
           tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec);
    
    // ctype.h
    char c = 'A';
    printf("%c is uppercase: %d\n", c, isupper(c));
    printf("%c to lowercase: %c\n", c, tolower(c));
    
    return 0;
}

5. advanceddatastructure

5.1 链表 advancedimplementation

链表 is a常用 动态datastructure, in Clanguagein可以throughstructure体 and 指针implementation.

// 双向链表implementation
#include <stdio.h>
#include <stdlib.h>

// 双向链表nodestructure体
typedef struct Node {
    int data;
    struct Node *prev;
    struct Node *next;
} Node;

// creation new node
Node *createNode(int data) {
    Node *newNode = (Node *)malloc(sizeof(Node));
    if (newNode != NULL) {
        newNode->data = data;
        newNode->prev = NULL;
        newNode->next = NULL;
    }
    return newNode;
}

//  in 链表末尾添加node
void append(Node **head, int data) {
    Node *newNode = createNode(data);
    if (newNode == NULL) {
        return;
    }
    
    if (*head == NULL) {
        *head = newNode;
        return;
    }
    
    Node *temp = *head;
    while (temp->next != NULL) {
        temp = temp->next;
    }
    
    temp->next = newNode;
    newNode->prev = temp;
}

// 显示链表
void display(Node *head) {
    if (head == NULL) {
        printf("链表 for 空\n");
        return;
    }
    
    Node *temp = head;
    printf("链表 in 容: ");
    while (temp != NULL) {
        printf("%d ", temp->data);
        temp = temp->next;
    }
    printf("\n");
}

// 释放链表
void freeList(Node *head) {
    Node *temp;
    while (head != NULL) {
        temp = head;
        head = head->next;
        free(temp);
    }
}

int main() {
    Node *head = NULL;
    
    // 添加node
    append(&head, 10);
    append(&head, 20);
    append(&head, 30);
    append(&head, 40);
    append(&head, 50);
    
    // 显示链表
    display(head);
    
    // 释放链表
    freeList(head);
    
    return 0;
}

5.2 treestructure

tree is a important 非线性datastructure, in Clanguagein可以throughstructure体 and 指针implementation.

// 二叉treeimplementation
#include <stdio.h>
#include <stdlib.h>

// 二叉treenodestructure体
typedef struct TreeNode {
    int data;
    struct TreeNode *left;
    struct TreeNode *right;
} TreeNode;

// creation new node
TreeNode *createTreeNode(int data) {
    TreeNode *newNode = (TreeNode *)malloc(sizeof(TreeNode));
    if (newNode != NULL) {
        newNode->data = data;
        newNode->left = NULL;
        newNode->right = NULL;
    }
    return newNode;
}

// 插入node (二叉搜索tree) 
TreeNode *insert(TreeNode *root, int data) {
    if (root == NULL) {
        return createTreeNode(data);
    }
    
    if (data < root->data) {
        root->left = insert(root->left, data);
    } else if (data > root->data) {
        root->right = insert(root->right, data);
    }
    
    return root;
}

// in序遍历
void inorderTraversal(TreeNode *root) {
    if (root != NULL) {
        inorderTraversal(root->left);
        printf("%d ", root->data);
        inorderTraversal(root->right);
    }
}

// 释放tree
void freeTree(TreeNode *root) {
    if (root != NULL) {
        freeTree(root->left);
        freeTree(root->right);
        free(root);
    }
}

int main() {
    TreeNode *root = NULL;
    
    // 插入node
    root = insert(root, 50);
    root = insert(root, 30);
    root = insert(root, 70);
    root = insert(root, 20);
    root = insert(root, 40);
    root = insert(root, 60);
    root = insert(root, 80);
    
    // in序遍历
    printf("in序遍历: ");
    inorderTraversal(root);
    printf("\n");
    
    // 释放tree
    freeTree(root);
    
    return 0;
}

6. performanceoptimizationtechniques

6.1 codeoptimization

  • reducingfunction调用开销: for 于频繁调用 small function, 可以考虑using in 联function (inline)
  • reducingmemory访问: using局部variable, 避免频繁访问全局variable
  • 循环optimization: reducing循环 in 计算, using循环unfoldtechniques
  • 条件branchoptimization: 将最可能 条件放 in before 面, using查表代替 complex 条件判断
  • algorithmsoptimization: 选择时间complexity更 low algorithms

6.2 memoryoptimization

  • reducingmemory分配次数: 预分配足够 memory, 避免频繁 动态memory分配
  • using合适 datastructure: 选择空间complexity low datastructure
  • memory for 齐: 合理安排structure体成员 顺序, reducingmemory padding
  • memory池: for 于频繁分配 and 释放 small memory, usingmemory池

6.3 编译器optimization

big many 数现代编译器都providing了 many 种optimization选项, 可以根据需要选择合适 optimization级别:

// 编译optimization选项
gcc -O0 -o program source.c  // 无optimization
 gcc -O1 -o program source.c  // basicoptimization
 gcc -O2 -o program source.c  // 更 many optimization
 gcc -O3 -o program source.c  // 最advancedoptimization
 gcc -Os -o program source.c  // optimizationcode big  small 

6.4 performanceanalysis

usingperformanceanalysistool可以helping识别codein performance瓶颈:

  • gprof: GNU performanceanalysistool
  • Valgrind: memoryanalysis and performanceanalysistool
  • perf: Linux performance计数器tool

实践case: many fileprojectDevelopment

writing一个Clanguage many fileproject, implementation一个 simple 学生informationmanagementsystem, package含以 under functions:

requirementsanalysis

  • 添加学生information
  • 显示学生information
  • 根据学号find学生
  • 根据成绩sort学生
  • 保存学生information to file
  • from file加载学生information

projectstructure

  • student.h: 学生structure体定义 and function声明
  • student.c: 学生相关functionimplementation
  • database.h: datalibraryoperationfunction声明
  • database.c: datalibraryoperationfunctionimplementation
  • main.c: 主function

referencecode

// student.h
#ifndef STUDENT_H
#define STUDENT_H

#define MAX_NAME_LEN 50

// 学生structure体
typedef struct {
    int id;
    char name[MAX_NAME_LEN];
    float score;
} Student;

// 学生相关function
void initStudent(Student *student, int id, const char *name, float score);
void printStudent(const Student *student);

#endif  // STUDENT_H

// student.c
#include <stdio.h>
#include "student.h"

void initStudent(Student *student, int id, const char *name, float score) {
    student->id = id;
    snprintf(student->name, MAX_NAME_LEN, "%s", name);
    student->score = score;
}

void printStudent(const Student *student) {
    printf("ID: %d, Name: %s, Score: %.2f\n", 
           student->id, student->name, student->score);
}

// database.h
#ifndef DATABASE_H
#define DATABASE_H

#include "student.h"

#define MAX_STUDENTS 100

// datalibrarystructure体
typedef struct {
    Student students[MAX_STUDENTS];
    int count;
} Database;

// datalibraryoperationfunction
void initDatabase(Database *db);
int addStudent(Database *db, const Student *student);
void printAllStudents(const Database *db);
Student *findStudentById(Database *db, int id);
void sortStudentsByScore(Database *db);
int saveDatabase(const Database *db, const char *filename);
int loadDatabase(Database *db, const char *filename);

#endif  // DATABASE_H

// database.c
#include <stdio.h>
#include "database.h"

void initDatabase(Database *db) {
    db->count = 0;
}

int addStudent(Database *db, const Student *student) {
    if (db->count >= MAX_STUDENTS) {
        return 0;  // datalibrary已满
    }
    
    db->students[db->count] = *student;
    db->count++;
    return 1;  // 添加成功
}

void printAllStudents(const Database *db) {
    printf("\n=== Student List ===\n");
    for (int i = 0; i < db->count; i++) {
        printStudent(&db->students[i]);
    }
    printf("====================\n");
}

Student *findStudentById(Database *db, int id) {
    for (int i = 0; i < db->count; i++) {
        if (db->students[i].id == id) {
            return &db->students[i];
        }
    }
    return NULL;  // 未找 to 
}

void sortStudentsByScore(Database *db) {
    for (int i = 0; i < db->count - 1; i++) {
        for (int j = 0; j < db->count - i - 1; j++) {
            if (db->students[j].score < db->students[j + 1].score) {
                // 交换
                Student temp = db->students[j];
                db->students[j] = db->students[j + 1];
                db->students[j + 1] = temp;
            }
        }
    }
}

int saveDatabase(const Database *db, const char *filename) {
    FILE *file = fopen(filename, "wb");
    if (file == NULL) {
        return 0;  // file打开失败
    }
    
    fwrite(&db->count, sizeof(int), 1, file);
    fwrite(db->students, sizeof(Student), db->count, file);
    
    fclose(file);
    return 1;  // 保存成功
}

int loadDatabase(Database *db, const char *filename) {
    FILE *file = fopen(filename, "rb");
    if (file == NULL) {
        return 0;  // file打开失败
    }
    
    fread(&db->count, sizeof(int), 1, file);
    if (db->count > MAX_STUDENTS) {
        db->count = MAX_STUDENTS;
    }
    fread(db->students, sizeof(Student), db->count, file);
    
    fclose(file);
    return 1;  // 加载成功
}

// main.c
#include <stdio.h>
#include "student.h"
#include "database.h"

int main() {
    Database db;
    initDatabase(&db);
    
    // 添加学生
    Student s1, s2, s3;
    initStudent(&s1, 1, "Alice", 95.5);
    initStudent(&s2, 2, "Bob", 88.0);
    initStudent(&s3, 3, "Charlie", 92.5);
    
    addStudent(&db, &s1);
    addStudent(&db, &s2);
    addStudent(&db, &s3);
    
    // 显示所 has 学生
    printAllStudents(&db);
    
    // find学生
    int searchId = 2;
    Student *found = findStudentById(&db, searchId);
    if (found != NULL) {
        printf("\nFound student with ID %d: ", searchId);
        printStudent(found);
    } else {
        printf("\nStudent with ID %d not found\n", searchId);
    }
    
    // sort学生
    sortStudentsByScore(&db);
    printf("\nStudents sorted by score: ");
    printAllStudents(&db);
    
    // 保存 to file
    const char *filename = "students.dat";
    if (saveDatabase(&db, filename)) {
        printf("\nDatabase saved to %s\n", filename);
    } else {
        printf("\nFailed to save database\n");
    }
    
    // 加载 from file
    Database db2;
    initDatabase(&db2);
    if (loadDatabase(&db2, filename)) {
        printf("\nDatabase loaded from %s\n", filename);
        printAllStudents(&db2);
    } else {
        printf("\nFailed to load database\n");
    }
    
    return 0;
}

互动练习

练习1: writing一个C程序, using位运算implementation一个 simple 位graph (bitmap) datastructure, 用于store整数collection.

要求: implementation添加, delete, find and 清空operation.

练习2: writing一个C程序, using预processing指令implementation一个跨平台 logsystem.

要求: in 不同平台 on using不同 log输出方式, support不同 log级别.

练习3: writing一个C程序, implementation一个 simple 哈希表datastructure.

要求: implementation插入, find and deleteoperation, processing哈希conflict.

练习4: writing一个C程序, usingmemory池techniquesoptimization频繁 memory分配 and 释放operation.

要求: implementationmemory池 初始化, 分配, 释放 and 销毁operation.