乐闻世界logo
搜索文章和话题

C语言面试题手册

C语言中位域(bit-field)的定义和使用场景是什么?

C语言中位域(bit-field)的定义和使用场景是什么?位域基本概念:基本定义 struct BitField { unsigned int flag1 : 1; // 1位 unsigned int flag2 : 1; // 1位 unsigned int value : 6; // 6位 unsigned int status : 4; // 4位 }; struct BitField bf; bf.flag1 = 1; bf.value = 42;位域大小 struct Example { unsigned int a : 3; // 0-7 unsigned int b : 5; // 0-31 unsigned int c : 8; // 0-255 }; sizeof(struct Example); // 通常为4字节使用场景:标志位管理 struct FileFlags { unsigned int read : 1; unsigned int write : 1; unsigned int execute : 1; unsigned int hidden : 1; unsigned int system : 1; unsigned int archive : 1; unsigned int reserved : 2; }; struct FileFlags flags = {0}; flags.read = 1; flags.write = 1;协议字段解析 struct IPHeader { unsigned int version : 4; unsigned int ihl : 4; unsigned int tos : 8; unsigned int total_length : 16; unsigned int identification : 16; unsigned int flags : 3; unsigned int fragment_offset : 13; }; struct IPHeader header; header.version = 4; header.ihl = 5;硬件寄存器映射 struct Register { unsigned int enable : 1; unsigned int mode : 2; unsigned int speed : 3; unsigned int reserved : 26; }; volatile struct Register *reg = (volatile struct Register*)0x40000000; reg->enable = 1; reg->mode = 2;颜色编码 struct RGB { unsigned int red : 8; unsigned int green : 8; unsigned int blue : 8; unsigned int alpha : 8; }; struct RGB color = {255, 128, 64, 255};高级特性:命名位域 struct PaddedBitField { unsigned int a : 4; unsigned int : 0; // 填充到下一个边界 unsigned int b : 4; };无名称位域 struct UnnamedBits { unsigned int flag1 : 1; unsigned int : 3; // 跳过3位 unsigned int flag2 : 1; };有符号位域 struct SignedBits { signed int value : 4; // -8 到 7 unsigned int uvalue : 4; // 0 到 15 };注意事项:跨平台兼容性 // 位域的布局依赖于编译器 struct Portable { unsigned int a : 8; unsigned int b : 8; }; // 不同编译器可能有不同的布局位域的地址 struct BitField { unsigned int a : 4; unsigned int b : 4; }; struct BitField bf; // &bf.a 是非法的,不能取位域的地址位域的限制 struct LimitExample { unsigned int value : 3; // 0-7 }; struct LimitExample le; le.value = 10; // 实际存储为 10 % 8 = 2实际应用示例:状态机压缩 struct StateMachine { unsigned int current_state : 3; unsigned int previous_state : 3; unsigned int error_code : 4; unsigned int flags : 6; }; struct StateMachine sm = {0}; sm.current_state = 2; sm.flags = 0x3F;网络数据包解析 struct TCPHeader { unsigned int source_port : 16; unsigned int dest_port : 16; unsigned int sequence_number : 32; unsigned int ack_number : 32; unsigned int data_offset : 4; unsigned int reserved : 3; unsigned int flags : 9; };音频格式描述 struct AudioFormat { unsigned int sample_rate : 4; unsigned int bit_depth : 4; unsigned int channels : 2; unsigned int format : 6; }; struct AudioFormat audio = { .sample_rate = 3, // 44.1kHz .bit_depth = 2, // 16-bit .channels = 1, // Stereo .format = 1 // PCM };
阅读 0·2月18日 17:21

C语言中restrict关键字的用途和优化效果是什么?

C语言中restrict关键字的用途和优化效果是什么?restrict 关键字基本概念:指针别名限制 void copy(int *restrict dest, const int *restrict src, size_t n) { for (size_t i = 0; i < n; i++) { dest[i] = src[i]; } } // dest 和 src 不会指向重叠的内存区域编译器优化 // 没有 restrict void add_arrays(int *a, int *b, int *c, int n) { for (int i = 0; i < n; i++) { a[i] = b[i] + c[i]; } } // 使用 restrict void add_arrays_optimized(int *restrict a, const int *restrict b, const int *restrict c, int n) { for (int i = 0; i < n; i++) { a[i] = b[i] + c[i]; } }使用场景:内存拷贝 void memcpy_custom(void *restrict dest, const void *restrict src, size_t n) { unsigned char *d = dest; const unsigned char *s = src; while (n--) { *d++ = *s++; } }数学运算 void vector_add(double *restrict result, const double *restrict a, const double *restrict b, size_t size) { for (size_t i = 0; i < size; i++) { result[i] = a[i] + b[i]; } }字符串处理 size_t strlen_custom(const char *restrict str) { size_t len = 0; while (*str++) len++; return len; }优化效果:循环展开 void process(int *restrict data, int n) { // 编译器可以安全地展开循环 for (int i = 0; i < n; i++) { data[i] *= 2; } }向量化 void scale_array(double *restrict arr, double factor, int n) { for (int i = 0; i < n; i++) { arr[i] *= factor; } // 编译器可以使用 SIMD 指令 }缓存优化 void matrix_multiply(double *restrict result, const double *restrict a, const double *restrict b, int rows, int cols, int k) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { result[i * cols + j] = 0; for (int p = 0; p < k; p++) { result[i * cols + j] += a[i * k + p] * b[p * cols + j]; } } } }注意事项:未定义行为 void dangerous(int *restrict a, int *restrict b) { *a = 10; *b = 20; // 如果 a 和 b 指向同一位置,行为未定义 }参数传递 void function(int *restrict p) { // p 在函数内部不会产生别名 } int main() { int x = 10; function(&x); // 安全 }结构体指针 struct Point { int x, y; }; void transform(struct Point *restrict p) { p->x *= 2; p->y *= 2; }实际应用示例:图像处理 void grayscale_image(unsigned char *restrict pixels, int width, int height) { for (int i = 0; i < width * height * 3; i += 3) { unsigned char gray = (pixels[i] + pixels[i+1] + pixels[i+2]) / 3; pixels[i] = pixels[i+1] = pixels[i+2] = gray; } }信号处理 void apply_filter(double *restrict output, const double *restrict input, const double *restrict kernel, int size, int kernel_size) { for (int i = 0; i < size; i++) { output[i] = 0; for (int j = 0; j < kernel_size; j++) { if (i + j < size) { output[i] += input[i + j] * kernel[j]; } } } }数据压缩 void compress_data(const int *restrict input, int *restrict output, int size) { int out_index = 0; int current = input[0]; int count = 1; for (int i = 1; i < size; i++) { if (input[i] == current) { count++; } else { output[out_index++] = current; output[out_index++] = count; current = input[i]; count = 1; } } }性能对比:无 restrict void add_slow(int *a, int *b, int *c, int n) { for (int i = 0; i < n; i++) { a[i] = b[i] + c[i]; } // 编译器必须考虑指针重叠 }有 restrict void add_fast(int *restrict a, const int *restrict b, const int *restrict c, int n) { for (int i = 0; i < n; i++) { a[i] = b[i] + c[i]; } // 编译器可以激进优化 }
阅读 0·2月18日 17:21

C语言中inline关键字的作用和使用限制是什么?

C语言中inline关键字的作用和使用限制是什么?inline 关键字基本概念:内联函数定义 inline int add(int a, int b) { return a + b; } int main() { int result = add(3, 5); // 编译器可能将函数调用展开为: result = 3 + 5; }内联的优势 // 消除函数调用开销 inline int square(int x) { return x * x; } // 使用 int y = square(10); // 可能展开为: int y = 10 * 10;使用场景:小型频繁调用的函数 inline int max(int a, int b) { return a > b ? a : b; } inline int min(int a, int b) { return a < b ? a : b; }访问器函数 struct Point { int x, y; }; inline int get_x(const struct Point *p) { return p->x; } inline void set_x(struct Point *p, int value) { p->x = value; }数学运算 inline double degrees_to_radians(double degrees) { return degrees * 3.14159265358979323846 / 180.0; } inline double radians_to_degrees(double radians) { return radians * 180.0 / 3.14159265358979323846; }使用限制:函数定义 // 头文件中 inline int add(int a, int b) { return a + b; } // 源文件中 extern inline int add(int a, int b);递归函数 // 递归函数不能完全内联 inline int factorial(int n) { return n <= 1 ? 1 : n * factorial(n - 1); }复杂函数 // 复杂函数可能不会被内联 inline void complex_function(int *data, int size) { for (int i = 0; i < size; i++) { data[i] = perform_complex_calculation(data[i]); } }最佳实践:头文件定义 // math_utils.h #ifndef MATH_UTILS_H #define MATH_UTILS_H static inline int abs(int x) { return x < 0 ? -x : x; } static inline int clamp(int value, int min, int max) { return value < min ? min : (value > max ? max : value); } #endif条件内联 #ifdef ALWAYS_INLINE #define INLINE __attribute__((always_inline)) inline #else #define INLINE inline #endif INLINE int fast_function(int x) { return x * 2; }编译器提示 // GCC/Clang inline __attribute__((always_inline)) int always_inline(int x) { return x * 2; } // MSVC __forceinline int force_inline(int x) { return x * 2; }性能考虑:代码膨胀 // 过度内联可能导致代码膨胀 inline int small_func(int x) { return x + 1; } // 如果在多个地方调用,会生成多份代码缓存影响 // 内联可能改善指令缓存 inline int fast_operation(int x) { return (x << 1) + (x << 3); // x * 10 }编译器决策 // 编译器可能忽略 inline 建议 inline int maybe_inlined(int x) { return x * x; } // 编译器根据优化级别决定是否内联实际应用示例:容器操作 struct Vector { int *data; size_t size; size_t capacity; }; static inline int vector_get(const struct Vector *v, size_t index) { return v->data[index]; } static inline void vector_set(struct Vector *v, size_t index, int value) { v->data[index] = value; }位操作 static inline int set_bit(int value, int bit) { return value | (1 << bit); } static inline int clear_bit(int value, int bit) { return value & ~(1 << bit); } static inline int toggle_bit(int value, int bit) { return value ^ (1 << bit); }字符串操作 static inline int string_equals(const char *a, const char *b) { return strcmp(a, b) == 0; } static inline int string_length(const char *str) { return strlen(str); }注意事项:链接规则 // 头文件中定义 inline int func(int x) { return x * 2; } // 多个文件包含头文件时,每个文件都有自己的定义调试困难 // 内联函数在调试时可能难以跟踪 inline int debug_func(int x) { return x + 1; }优化级别 // 不同优化级别下,inline 效果不同 // -O0: 可能不内联 // -O2, -O3: 更可能内联
阅读 0·2月18日 17:20

C语言中extern关键字的作用和链接机制是什么?

C语言中extern关键字的作用和链接机制是什么?extern 关键字基本概念:声明外部变量 // file1.c int global_var = 100; // file2.c extern int global_var; // 声明,不分配内存 void function() { global_var = 200; // 访问 file1.c 中的变量 }声明外部函数 // file1.c int add(int a, int b) { return a + b; } // file2.c extern int add(int a, int b); // 可省略 extern void use_add() { int result = add(3, 5); }链接机制:内部链接 vs 外部链接 // 内部链接(static) static int internal_var = 10; static void internal_func() {} // 外部链接(默认) int external_var = 20; void external_func() {} // 显式外部链接 extern int explicit_var = 30; extern void explicit_func() {}跨文件共享 // config.h extern int MAX_CONNECTIONS; extern const char* LOG_FILE; // config.c int MAX_CONNECTIONS = 100; const char* LOG_FILE = "app.log"; // main.c #include "config.h" int main() { printf("Max connections: %d\n", MAX_CONNECTIONS); }使用场景:头文件声明 // mylib.h #ifndef MYLIB_H #define MYLIB_H extern int library_version; extern void library_init(); extern void library_cleanup(); #endif避免重复定义 // common.h extern int shared_counter; // file1.c #include "common.h" int shared_counter = 0; // 定义 // file2.c #include "common.h" // 只声明,不定义条件编译 // platform.h #ifdef _WIN32 extern void windows_specific(); #elif defined(__linux__) extern void linux_specific(); #endif注意事项:声明 vs 定义 // 声明(不分配内存) extern int var1; // 定义(分配内存) int var1 = 10; extern int var2 = 20; // 也是定义const 变量的 extern // 默认情况下 const 变量是内部链接 const int CONSTANT = 100; // 需要显式声明为外部链接 extern const int EXTERN_CONSTANT = 200;初始化 // 正确 extern int var; // 声明 int var = 10; // 定义 // 错误 extern int var = 10; // 虽然合法,但不推荐高级应用:动态链接库 // mylib.c __declspec(dllexport) int lib_function(int x) { return x * 2; } // main.c __declspec(dllimport) int lib_function(int x);内联函数 // header.h static inline int max(int a, int b) { return a > b ? a : b; }宏与 extern 结合 // api.h #ifdef API_EXPORTS #define API __declspec(dllexport) #else #define API __declspec(dllimport) #endif API void api_function();最佳实践:头文件组织 // module.h #ifndef MODULE_H #define MODULE_H #ifdef __cplusplus extern "C" { #endif extern int module_init(); extern void module_cleanup(); #ifdef __cplusplus } #endif #endif避免全局变量 // 不推荐 extern int global_state; // 推荐:使用访问函数 int get_state(); void set_state(int value);命名空间模拟 // network.h extern int network_init(); extern void network_send(const char* data); // file.h extern int file_open(const char* path); extern void file_write(int fd, const char* data);常见错误:重复定义 // file1.c int shared_var = 10; // file2.c int shared_var = 20; // 链接错误:重复定义未定义引用 // file1.c extern int undefined_var; void function() { int x = undefined_var; // 链接错误:未定义引用 }类型不匹配 // file1.c int value = 10; // file2.c extern double value; // 链接错误:类型不匹配
阅读 0·2月18日 17:20

C语言中静态(static)关键字的作用域和生命周期是什么?

C语言中静态(static)关键字的作用域和生命周期是什么?static 关键字的三种用法:静态局部变量 void counter() { static int count = 0; // 只初始化一次 count++; printf("Count: %d\n", count); } int main() { counter(); // Count: 1 counter(); // Count: 2 counter(); // Count: 3 }静态全局变量 static int global_var = 100; // 文件作用域 void function() { global_var++; } // 其他文件无法访问 global_var静态函数 static void helper_function() { printf("This is a static function\n"); } // 只能在当前文件中调用作用域和生命周期:静态局部变量 void example() { // 作用域:函数内部 // 生命周期:整个程序运行期间 static int value = 10; // 每次调用都保留上次的值 value++; }静态全局变量 // file1.c static int file_global = 50; // file2.c extern int file_global; // 链接错误静态函数 // file1.c static int internal_calculation(int x) { return x * 2; } // file2.c int internal_calculation(int x); // 链接错误实际应用场景:单例模式 int* get_instance() { static int *instance = NULL; if (instance == NULL) { instance = malloc(sizeof(int)); *instance = 0; } return instance; }缓存机制 int expensive_calculation(int n) { static int cache[100] = {0}; if (n < 100 && cache[n] != 0) { return cache[n]; } int result = /* 复杂计算 */; if (n < 100) { cache[n] = result; } return result; }计数器 int get_unique_id() { static int next_id = 0; return next_id++; }状态保持 void state_machine() { static enum { INIT, RUNNING, DONE } state = INIT; switch (state) { case INIT: printf("Initializing...\n"); state = RUNNING; break; case RUNNING: printf("Running...\n"); state = DONE; break; case DONE: printf("Done!\n"); break; } }与 const 的区别:static vs const // static: 控制作用域和生命周期 static int value = 10; // const: 控制可修改性 const int value = 10; // 可以组合使用 static const int CONSTANT = 100;线程安全考虑:非线程安全的静态变量 int* get_instance_unsafe() { static int *instance = NULL; // 非线程安全 if (instance == NULL) { instance = malloc(sizeof(int)); } return instance; }线程安全的静态变量 #include <pthread.h> int* get_instance_safe() { static int *instance = NULL; static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&mutex); if (instance == NULL) { instance = malloc(sizeof(int)); } pthread_mutex_unlock(&mutex); return instance; }最佳实践:信息隐藏 // module.c static int internal_state = 0; static void internal_helper() { internal_state++; } void public_interface() { internal_helper(); }避免全局变量污染 // 使用 static 限制作用域 static int module_config = 0; void set_config(int value) { module_config = value; }初始化顺序 void function() { static int initialized = 0; static int cache[100]; if (!initialized) { for (int i = 0; i < 100; i++) { cache[i] = i * i; } initialized = 1; } return cache[10]; }
阅读 0·2月18日 17:18

C语言中可变参数函数的实现原理和使用方法是什么?

C语言中可变参数函数的实现原理和使用方法是什么?可变参数函数基础:基本定义 #include <stdarg.h> int sum(int count, ...) { va_list args; va_start(args, count); int total = 0; for (int i = 0; i < count; i++) { total += va_arg(args, int); } va_end(args); return total; } int result = sum(3, 10, 20, 30);核心宏 va_list args; // 声明参数列表 va_start(args, last); // 初始化参数列表 va_arg(args, type); // 获取下一个参数 va_end(args); // 清理参数列表典型应用场景:格式化输出 void debug_print(const char *format, ...) { va_list args; va_start(args, format); #ifdef DEBUG vprintf(format, args); #endif va_end(args); } debug_print("Value: %d, String: %s\n", 42, "Hello");自定义错误处理 void error_handler(int code, const char *format, ...) { va_list args; va_start(args, format); fprintf(stderr, "Error %d: ", code); vfprintf(stderr, format, args); fprintf(stderr, "\n"); va_end(args); } error_handler(404, "File %s not found", "config.txt");字符串构建 char* string_build(const char *format, ...) { va_list args; va_start(args, format); int size = vsnprintf(NULL, 0, format, args); va_end(args); char *buffer = malloc(size + 1); if (buffer) { va_start(args, format); vsnprintf(buffer, size + 1, format, args); va_end(args); } return buffer; }高级用法:类型安全检查 void safe_printf(const char *format, ...) { va_list args; va_start(args, format); const char *p = format; while (*p) { if (*p == '%') { p++; switch (*p) { case 'd': va_arg(args, int); break; case 'f': va_arg(args, double); break; case 's': va_arg(args, char*); break; } } p++; } va_end(args); }可变参数计数 int count_args(int first, ...) { if (first == -1) return 0; va_list args; va_start(args, first); int count = 1; int value; while ((value = va_arg(args, int)) != -1) { count++; } va_end(args); return count; }传递可变参数 void wrapper_printf(const char *format, ...) { va_list args; va_start(args, format); vprintf(format, args); va_end(args); }注意事项:参数类型匹配 // 危险:类型不匹配 void example(const char *format, ...) { va_list args; va_start(args, format); int i = va_arg(args, int); // 必须与实际参数类型匹配 double d = va_arg(args, double); va_end(args); }默认参数提升 void promoted_args(...) { va_list args; va_start(args, 0); // char 和 short 会提升为 int // float 会提升为 double int i = va_arg(args, int); double d = va_arg(args, double); va_end(args); }内存管理 void process_strings(...) { va_list args; va_start(args, 0); char *str; while ((str = va_arg(args, char*)) != NULL) { // 处理字符串 // 注意:不释放字符串 } va_end(args); }实际应用示例:日志系统 typedef enum { LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR } LogLevel; void log_message(LogLevel level, const char *format, ...) { const char *level_str[] = {"DEBUG", "INFO", "WARN", "ERROR"}; printf("[%s] ", level_str[level]); va_list args; va_start(args, format); vprintf(format, args); va_end(args); printf("\n"); }配置解析 void parse_config(const char *key, ...) { va_list args; va_start(args, key); void *ptr; while ((ptr = va_arg(args, void*)) != NULL) { // 解析配置并存储到指针 } va_end(args); } int port, timeout; parse_config("server", &port, &timeout, NULL);数组求和 double sum_array(int count, ...) { va_list args; va_start(args, count); double sum = 0.0; for (int i = 0; i < count; i++) { sum += va_arg(args, double); } va_end(args); return sum; } double result = sum_array(3, 1.5, 2.5, 3.5);
阅读 0·2月18日 17:17

C语言中位运算符的完整用法和实际应用场景是什么?

C语言中位运算符的完整用法和实际应用场景是什么?位运算符列表:按位与 & unsigned int a = 0b10101010; // 170 unsigned int b = 0b11001100; // 204 unsigned int result = a & b; // 0b10001000 (136)按位或 | unsigned int result = a | b; // 0b11101110 (238)按位异或 ^ unsigned int result = a ^ b; // 0b01100110 (102)按位取反 ~ unsigned int result = ~a; // 0b01010101 (85)左移 unsigned int result = a << 2; // 0b1010101000 (680)右移 >> unsigned int result = a >> 2; // 0b00101010 (42)实际应用场景:位掩码操作 #define FLAG_A 0x01 // 00000001 #define FLAG_B 0x02 // 00000010 #define FLAG_C 0x04 // 00000100 unsigned int flags = 0; // 设置标志位 flags |= FLAG_A; flags |= FLAG_B; // 清除标志位 flags &= ~FLAG_A; // 检查标志位 if (flags & FLAG_B) { printf("FLAG_B is set\n"); } // 切换标志位 flags ^= FLAG_C;位域操作 struct BitField { unsigned int flag1 : 1; unsigned int flag2 : 1; unsigned int value : 6; };快速计算 // 乘以2的幂 int x = 5; int result = x << 3; // x * 8 = 40 // 除以2的幂 int result = x >> 2; // x / 4 = 1 // 判断奇偶 if (x & 1) { printf("Odd\n"); } else { printf("Even\n"); }数据压缩 // 将两个8位值打包成16位 uint8_t low = 0xAB; uint8_t high = 0xCD; uint16_t packed = (high << 8) | low; // 0xCDAB // 解包 uint8_t extracted_low = packed & 0xFF; uint8_t extracted_high = (packed >> 8) & 0xFF;哈希计算 unsigned int hash = 0; for (int i = 0; i < len; i++) { hash = (hash << 5) ^ str[i]; }注意事项:有符号数的右移行为依赖于实现位运算优先级低于比较运算符避免对负数进行位运算移位次数不能超过或等于类型的位数
阅读 0·2月18日 17:17

C语言中递归函数的实现原理和优化技巧是什么?

C语言中递归函数的实现原理和优化技巧是什么?递归函数原理:基本结构 // 递归函数三要素 // 1. 基准情况(终止条件) // 2. 递归调用 // 3. 向基准情况逼近 int factorial(int n) { if (n <= 1) { // 基准情况 return 1; } return n * factorial(n - 1); // 递归调用 }调用栈机制 void recursive_function(int n) { if (n <= 0) return; // 每次调用都会在栈上创建新的栈帧 // 保存局部变量、返回地址等 printf("Before: %d\n", n); recursive_function(n - 1); printf("After: %d\n", n); }经典递归示例:斐波那契数列 // 基础版本(效率低) int fibonacci(int n) { if (n <= 1) return n; return fibonacci(n - 1) + fibonacci(n - 2); } // 优化版本(记忆化) int fib_memo(int n, int *memo) { if (n <= 1) return n; if (memo[n] != -1) return memo[n]; memo[n] = fib_memo(n - 1, memo) + fib_memo(n - 2, memo); return memo[n]; }二分查找 int binary_search(int arr[], int left, int right, int target) { if (left > right) return -1; int mid = left + (right - left) / 2; if (arr[mid] == target) return mid; if (arr[mid] > target) { return binary_search(arr, left, mid - 1, target); } return binary_search(arr, mid + 1, right, target); }快速排序 void quick_sort(int arr[], int low, int high) { if (low < high) { int pi = partition(arr, low, high); quick_sort(arr, low, pi - 1); quick_sort(arr, pi + 1, high); } }优化技巧:尾递归优化 // 普通递归 int factorial(int n) { if (n <= 1) return 1; return n * factorial(n - 1); } // 尾递归版本 int factorial_tail(int n, int accumulator) { if (n <= 1) return accumulator; return factorial_tail(n - 1, n * accumulator); } // 调用方式 int result = factorial_tail(5, 1);记忆化技术 #define MAX_N 1000 int memo[MAX_N]; int fibonacci_optimized(int n) { if (n <= 1) return n; if (memo[n] != 0) return memo[n]; return memo[n] = fibonacci_optimized(n - 1) + fibonacci_optimized(n - 2); }递归转迭代 // 递归版本 int sum_recursive(int n) { if (n <= 0) return 0; return n + sum_recursive(n - 1); } // 迭代版本 int sum_iterative(int n) { int sum = 0; for (int i = 1; i <= n; i++) { sum += i; } return sum; }注意事项:栈溢出风险 // 危险:深度递归可能导致栈溢出 int deep_recursion(int n) { if (n <= 0) return 0; return deep_recursion(n - 1); }性能考虑递归有函数调用开销可能重复计算栈空间消耗大适用场景树和图的遍历分治算法动态规划回溯算法
阅读 0·2月18日 17:16

C语言中文件操作的完整流程和错误处理机制是什么?

C语言中文件操作的完整流程和错误处理机制是什么?文件操作流程:打开文件 FILE *fopen(const char *filename, const char *mode); // 模式选项 "r" // 只读 "w" // 只写(覆盖) "a" // 追加 "r+" // 读写 "w+" // 读写(覆盖) "a+" // 读写(追加) // 二进制模式 "rb", "wb", "ab", "rb+", "wb+", "ab+" FILE *fp = fopen("data.txt", "r"); if (fp == NULL) { perror("Failed to open file"); return 1; }读取文件 // 字符读取 int fgetc(FILE *stream); char *fgets(char *str, int n, FILE *stream); // 格式化读取 int fscanf(FILE *stream, const char *format, ...); // 块读取 size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); // 示例 char buffer[256]; while (fgets(buffer, sizeof(buffer), fp) != NULL) { printf("%s", buffer); }写入文件 // 字符写入 int fputc(int c, FILE *stream); int fputs(const char *str, FILE *stream); // 格式化写入 int fprintf(FILE *stream, const char *format, ...); // 块写入 size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); // 示例 fprintf(fp, "Name: %s, Age: %d\n", name, age);文件定位 int fseek(FILE *stream, long offset, int origin); // origin: SEEK_SET, SEEK_CUR, SEEK_END long ftell(FILE *stream); void rewind(FILE *stream); // 示例 fseek(fp, 0, SEEK_END); // 移动到文件末尾 long size = ftell(fp); // 获取文件大小 rewind(fp); // 回到文件开头关闭文件 int fclose(FILE *stream); fclose(fp);错误处理机制:检查返回值 if (ferror(fp)) { perror("Error reading file"); } if (feof(fp)) { printf("End of file reached\n"); }错误码处理 errno = 0; FILE *fp = fopen("nonexistent.txt", "r"); if (fp == NULL) { if (errno == ENOENT) { printf("File does not exist\n"); } else { perror("Error opening file"); } }清除错误状态 clearerr(fp); // 清除错误和EOF标志最佳实践:资源管理 FILE *fp = fopen("data.txt", "r"); if (!fp) { return -1; } // 使用 goto 进行错误处理 if (process_data(fp) != 0) { goto cleanup; } cleanup: if (fp) fclose(fp);缓冲控制 setvbuf(fp, NULL, _IOFBF, 4096); // 全缓冲 setvbuf(fp, NULL, _IOLBF, 4096); // 行缓冲 setvbuf(fp, NULL, _IONBF, 0); // 无缓冲临时文件 FILE *tmpfp = tmpfile(); if (tmpfp) { // 使用临时文件 fclose(tmpfp); // 自动删除 }
阅读 0·2月18日 17:15

C语言中函数指针和回调函数的实现原理是什么?

C语言中函数指针和回调函数的实现原理是什么?函数指针基础:函数指针声明 // 返回类型 (*指针名)(参数列表) int (*func_ptr)(int, int); // 指向函数的指针 int add(int a, int b) { return a + b; } func_ptr = add; // 通过指针调用函数 int result = func_ptr(3, 5); // 等同于 add(3, 5)函数指针数组 int (*operations[])(int, int) = {add, subtract, multiply}; int result = operations[0](10, 5); // 调用 add作为函数参数 void process_array(int *arr, int size, int (*callback)(int)) { for (int i = 0; i < size; i++) { arr[i] = callback(arr[i]); } }回调函数实现:排序回调 int compare_asc(const void *a, const void *b) { return (*(int*)a - *(int*)b); } int arr[] = {5, 2, 8, 1, 9}; qsort(arr, 5, sizeof(int), compare_asc);事件处理回调 typedef void (*EventHandler)(void); void on_click() { printf("Button clicked!\n"); } void register_event(EventHandler handler) { handler(); // 触发回调 }异步操作回调 typedef void (*AsyncCallback)(int result, void *user_data); void async_operation(AsyncCallback callback, void *data) { // 模拟异步操作 int result = perform_task(); callback(result, data); }高级应用:状态机实现 typedef void (*StateHandler)(void); void state_idle() { /* ... */ } void state_running() { /* ... */ } void state_paused() { /* ... */ } StateHandler states[] = {state_idle, state_running, state_paused}; int current_state = 0; states[current_state]();策略模式 typedef int (*Strategy)(int, int); int strategy_max(int a, int b) { return a > b ? a : b; } int strategy_min(int a, int b) { return a < b ? a : b; } void execute_strategy(Strategy strategy, int x, int y) { printf("Result: %d\n", strategy(x, y)); }注意事项:函数指针类型必须完全匹配空指针检查是必要的回调函数的上下文管理很重要
阅读 0·2月18日 17:13