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

C语言面试题手册

C语言中枚举类型的定义和使用技巧有哪些?

C语言中枚举类型的定义和使用技巧有哪些?枚举类型基础:基本定义 enum Color { RED, GREEN, BLUE }; enum Color c = RED;指定值 enum Status { SUCCESS = 0, ERROR = -1, PENDING = 1, COMPLETED = 2 };匿名枚举 enum { MAX_SIZE = 100, BUFFER_SIZE = 1024 };高级用法:枚举作为位标志 enum FileFlags { READ = 0x01, // 0001 WRITE = 0x02, // 0010 EXECUTE = 0x04, // 0100 APPEND = 0x08 // 1000 }; unsigned int flags = READ | WRITE; if (flags & READ) { printf("Read permission\n"); }枚举与switch配合 enum Day { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }; void print_day(enum Day day) { switch (day) { case MONDAY: printf("Monday\n"); break; case TUESDAY: printf("Tuesday\n"); break; default: printf("Other day\n"); } }枚举类型转换 enum Color { RED, GREEN, BLUE }; // 枚举到整数 int value = RED; // value = 0 // 整数到枚举 enum Color c = (enum Color)1; // GREEN // 枚举大小 printf("Size of enum: %zu\n", sizeof(enum Color));最佳实践:命名约定 // 使用大写和下划线 enum ErrorCode { ERROR_NONE, ERROR_INVALID_PARAM, ERROR_OUT_OF_MEMORY, ERROR_FILE_NOT_FOUND }; // 或使用前缀 enum SocketType { SOCK_TYPE_STREAM, SOCK_TYPE_DGRAM };枚举作为数组索引 enum Month { JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC }; const char* month_names[] = { "", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; printf("%s\n", month_names[JAN]);枚举与typedef结合 typedef enum { STATE_IDLE, STATE_RUNNING, STATE_PAUSED, STATE_STOPPED } State; State current_state = STATE_IDLE;注意事项:枚举值的连续性 enum Example { A = 1, B = 2, C = 5, // 不连续 D = 6 }; // 不能假设枚举值是连续的枚举的范围 enum Small { MIN = 0, MAX = 255 }; // 编译器可能选择更大的类型 // 不能保证只占用1字节枚举的前向声明 // C11 支持 enum Color; void process_color(enum Color c); enum Color { RED, GREEN, BLUE };实际应用示例:状态机实现 typedef enum { STATE_INIT, STATE_CONNECTING, STATE_CONNECTED, STATE_DISCONNECTING, STATE_ERROR } ConnectionState; ConnectionState handle_state(ConnectionState state) { switch (state) { case STATE_INIT: return STATE_CONNECTING; case STATE_CONNECTING: return STATE_CONNECTED; case STATE_CONNECTED: return STATE_DISCONNECTING; default: return STATE_ERROR; } }配置选项 enum ConfigOption { OPT_DEBUG = 0x01, OPT_VERBOSE = 0x02, OPT_LOG_FILE = 0x04, OPT_DAEMON = 0x08 }; void configure(unsigned int options) { if (options & OPT_DEBUG) { enable_debug(); } if (options & OPT_DAEMON) { run_as_daemon(); } }错误码定义 enum LibraryError { LIB_OK = 0, LIB_ERR_INVALID_ARG = -1, LIB_ERR_OUT_OF_MEMORY = -2, LIB_ERR_IO = -3, LIB_ERR_TIMEOUT = -4 }; enum LibraryError library_init() { if (!allocate_memory()) { return LIB_ERR_OUT_OF_MEMORY; } return LIB_OK; }
阅读 0·2月18日 17:22

C语言中结构体和类的区别及使用场景是什么?

C语言中结构体和类的区别及使用场景是什么?结构体基本概念:结构体定义 struct Point { int x; int y; }; struct Point p1 = {10, 20}; struct Point p2 = {.x = 30, .y = 40};结构体指针 struct Point *ptr = &p1; ptr->x = 50; ptr->y = 60;与类的对比:数据封装 // C语言结构体 struct Rectangle { int width; int height; }; // C++类 class Rectangle { private: int width; int height; public: Rectangle(int w, int h) : width(w), height(h) {} int area() { return width * height; } };方法定义 // C语言:使用函数指针 struct Shape { int (*area)(struct Shape*); int (*perimeter)(struct Shape*); }; int rectangle_area(struct Shape *s) { struct Rectangle *r = (struct Rectangle*)s; return r->width * r->height; } // C++:成员函数 class Shape { public: virtual int area() = 0; virtual int perimeter() = 0; };构造和析构 // C语言:手动初始化 struct Point create_point(int x, int y) { struct Point p = {x, y}; return p; } void destroy_point(struct Point *p) { // 手动清理资源 } // C++:自动构造和析构 class Point { public: Point(int x, int y) : x(x), y(y) {} ~Point() {} private: int x, y; };使用场景:数据结构 struct Node { int data; struct Node *next; }; struct LinkedList { struct Node *head; int size; };配置管理 struct Config { char server[256]; int port; int timeout; int max_connections; }; struct Config load_config(const char *filename);网络协议 struct PacketHeader { unsigned int version : 4; unsigned int type : 4; unsigned int length : 16; unsigned int checksum : 8; };高级特性:结构体嵌套 struct Address { char street[100]; char city[50]; char country[50]; }; struct Person { char name[50]; int age; struct Address address; }; struct Person person = { .name = "John Doe", .age = 30, .address = { .street = "123 Main St", .city = "New York", .country = "USA" } };结构体数组 struct Student { int id; char name[50]; float score; }; struct Student students[100]; students[0].id = 1; strcpy(students[0].name, "Alice"); students[0].score = 95.5;灵活数组成员 struct String { size_t length; char data[]; // 灵活数组成员 }; struct String *create_string(const char *str) { size_t len = strlen(str); struct String *s = malloc(sizeof(struct String) + len + 1); s->length = len; strcpy(s->data, str); return s; }最佳实践:命名约定 struct Point { int x; int y; }; typedef struct Point Point; Point p1 = {10, 20};初始化函数 struct Point point_create(int x, int y) { struct Point p = {x, y}; return p; } struct Point p = point_create(10, 20);内存管理 struct Point *point_alloc(int x, int y) { struct Point *p = malloc(sizeof(struct Point)); if (p) { p->x = x; p->y = y; } return p; } void point_free(struct Point *p) { free(p); }注意事项:内存对齐 struct Example { char c; // 1字节 + 3字节填充 int i; // 4字节 }; // 总大小: 8字节结构体赋值 struct Point p1 = {10, 20}; struct Point p2 = p1; // 浅拷贝结构体比较 struct Point p1 = {10, 20}; struct Point p2 = {10, 20}; // 错误:不能直接比较结构体 // if (p1 == p2) { } // 正确:逐个成员比较 if (p1.x == p2.x && p1.y == p2.y) { printf("Equal\n"); }
阅读 0·2月18日 17:22

C语言中动态内存管理的完整指南和常见问题是什么?

C语言中动态内存管理的完整指南和常见问题是什么?动态内存分配函数:malloc - 分配内存 void *malloc(size_t size); // 分配指定字节数的内存 int *arr = (int*)malloc(10 * sizeof(int)); if (arr == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } // 使用内存 for (int i = 0; i < 10; i++) { arr[i] = i * i; } // 释放内存 free(arr);calloc - 分配并初始化 void *calloc(size_t num, size_t size); // 分配并初始化为零 int *arr = (int*)calloc(10, sizeof(int)); // 所有元素自动初始化为0 free(arr);realloc - 重新分配 void *realloc(void *ptr, size_t size); int *arr = (int*)malloc(5 * sizeof(int)); // 扩展内存 int *new_arr = (int*)realloc(arr, 10 * sizeof(int)); if (new_arr == NULL) { free(arr); // 原内存仍然有效 exit(1); } arr = new_arr; free(arr);free - 释放内存 void free(void *ptr); int *ptr = (int*)malloc(sizeof(int)); free(ptr); ptr = NULL; // 避免悬空指针内存管理最佳实践:检查分配结果 void *ptr = malloc(size); if (ptr == NULL) { // 处理内存分配失败 return NULL; }避免内存泄漏 void function_with_leak() { int *ptr = malloc(sizeof(int)); // 忘记 free(ptr) - 内存泄漏 } void correct_function() { int *ptr = malloc(sizeof(int)); if (ptr) { // 使用内存 free(ptr); } }防止悬空指针 int *ptr = malloc(sizeof(int)); free(ptr); ptr = NULL; // 避免使用已释放的内存 // 错误示例 *ptr = 10; // 未定义行为双重释放防护 int *ptr = malloc(sizeof(int)); free(ptr); ptr = NULL; // 设置为NULL free(ptr); // free(NULL) 是安全的常见问题和解决方案:内存碎片 // 问题:频繁分配和释放不同大小的内存 for (int i = 0; i < 1000; i++) { void *ptr = malloc(rand() % 1000); free(ptr); } // 解决:使用内存池或固定大小分配缓冲区溢出 // 危险 int *arr = malloc(10 * sizeof(int)); arr[10] = 100; // 越界访问 // 安全 int *arr = malloc(10 * sizeof(int)); if (index < 10) { arr[index] = value; }野指针 int *ptr; // 未初始化 *ptr = 10; // 未定义行为 // 正确做法 int *ptr = NULL; ptr = malloc(sizeof(int)); if (ptr) { *ptr = 10; free(ptr); ptr = NULL; }高级技巧:自定义内存分配器 void* my_malloc(size_t size) { void *ptr = malloc(size); if (ptr) { memset(ptr, 0, size); // 清零 } return ptr; }内存调试 #ifdef DEBUG void *debug_malloc(size_t size, const char *file, int line) { void *ptr = malloc(size); printf("Allocated %zu bytes at %p (%s:%d)\n", size, ptr, file, line); return ptr; } #define MALLOC(size) debug_malloc(size, __FILE__, __LINE__) #else #define MALLOC(size) malloc(size) #endif
阅读 0·2月18日 17:21

C语言中typedef和#define的区别及使用场景是什么?

C语言中typedef和#define的区别及使用场景是什么?核心区别:处理阶段#define: 预处理器阶段,文本替换typedef: 编译器阶段,类型别名作用域#define: 全局作用域,从定义点到文件末尾typedef: 遵循正常作用域规则类型检查#define: 无类型检查,纯文本替换typedef: 有类型检查,编译器验证调试支持#define: 调试时显示原始代码typedef: 调试时显示别名类型使用场景对比:类型别名 // typedef - 推荐 typedef unsigned int uint32_t; uint32_t value = 100; // #define - 不推荐 #define uint32_t unsigned int uint32_t value = 100;函数指针 // typedef - 清晰易读 typedef int (*CompareFunc)(const void*, const void*); CompareFunc compare = my_compare; // #define - 难以理解 #define CompareFunc int (*)(const void*, const void*) CompareFunc compare = my_compare;结构体 // typedef - 简洁 typedef struct { int x; int y; } Point; Point p1 = {10, 20}; // #define - 不适用数组类型 // typedef - 类型安全 typedef int Array10[10]; Array10 arr1, arr2; // #define - 可能导致意外行为 #define Array10 int[10] Array10 arr1, arr2; // 只有arr2是数组#define 的优势场景:常量定义 #define MAX_SIZE 100 #define PI 3.14159 #define VERSION "1.0.0"条件编译 #ifdef DEBUG #define LOG(x) printf x #else #define LOG(x) #endif宏函数 #define SQUARE(x) ((x) * (x)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))typedef 的优势场景:提高代码可读性 typedef unsigned long long ull; typedef struct Node* NodePtr;跨平台兼容性 #ifdef _WIN64 typedef __int64 intptr_t; #else typedef long intptr_t; #endif回调函数类型 typedef void (*Callback)(int result); void register_callback(Callback cb);常见陷阱:宏的副作用 #define SQUARE(x) ((x) * (x)) int i = 2; int result = SQUARE(i++); // 未定义行为宏的括号问题 #define MUL(a, b) a * b int result = MUL(2 + 3, 4); // 结果是14,不是20typedef 不能用于数组初始化 typedef int IntArray[10]; IntArray arr = {1, 2, 3}; // 错误 int arr[10] = {1, 2, 3}; // 正确
阅读 0·2月18日 17:21

C语言中联合体(union)的使用场景和内存布局是什么?

C语言中联合体(union)的使用场景和内存布局是什么?联合体基本概念:定义和声明 union Data { int i; float f; char str[20]; }; union Data data; data.i = 10; data.f = 3.14; strcpy(data.str, "Hello");内存共享特性 union Example { int value; char bytes[4]; }; union Example ex; ex.value = 0x12345678; // bytes[0] = 0x78 (小端序) // bytes[1] = 0x56 // bytes[2] = 0x34 // bytes[3] = 0x12典型使用场景:数据类型转换 union FloatInt { float f; unsigned int i; }; float_to_bits(float value) { union FloatInt converter; converter.f = value; return converter.i; }节省内存空间 // 不使用联合体:占用12字节 struct Message { int type; union { int int_data; float float_data; char char_data[4]; } data; }; // 使用联合体:只占用8字节 union CompactMessage { struct { int type; int data; } int_msg; struct { int type; float data; } float_msg; };网络协议解析 union IPHeader { struct { unsigned int version : 4; unsigned int ihl : 4; unsigned int tos : 8; unsigned int total_length : 16; } fields; unsigned int raw; };变体数据类型 enum DataType { INT, FLOAT, STRING }; struct Variant { enum DataType type; union { int int_val; float float_val; char *str_val; } value; };内存布局分析:大小计算 union SizeExample { char c; // 1字节 int i; // 4字节 double d; // 8字节 }; sizeof(union SizeExample); // 8字节(最大成员的大小)对齐规则 union AlignedExample { char c; int i; double d; }; // 大小为8字节,对齐到8字节边界高级应用:位域操作 union BitManipulation { unsigned int value; struct { unsigned int bit0 : 1; unsigned int bit1 : 1; unsigned int bit2 : 1; unsigned int rest : 29; } bits; }; union BitManipulation bm; bm.value = 0; bm.bits.bit0 = 1;类型安全的联合体 struct SafeUnion { enum { INT, FLOAT, STRING } type; union { int int_val; float float_val; char *str_val; } data; }; void print_safe_union(struct SafeUnion *su) { switch (su->type) { case INT: printf("%d\n", su->data.int_val); break; case FLOAT: printf("%f\n", su->data.float_val); break; case STRING: printf("%s\n", su->data.str_val); break; } }注意事项:同时访问问题 union Data { int i; float f; }; union Data d; d.i = 10; d.f = 3.14; // 覆盖了之前的值 // 此时访问 d.i 是未定义行为字节序依赖 union EndianTest { int value; char bytes[4]; }; union EndianTest test; test.value = 1; if (test.bytes[0] == 1) { printf("Little Endian\n"); } else { printf("Big Endian\n"); }初始化 union Data { int i; float f; }; union Data d1 = {10}; // 初始化第一个成员 union Data d2 = {.f = 3.14}; // 指定成员初始化
阅读 0·2月18日 17:21

C语言中字符串处理函数的完整列表和最佳实践是什么?

C语言中字符串处理函数的完整列表和最佳实践是什么?核心字符串函数:字符串长度 size_t strlen(const char *str); // 返回字符串长度,不包含终止符 '\0'字符串复制 char *strcpy(char *dest, const char *src); char *strncpy(char *dest, const char *src, size_t n); // strncpy 不会自动添加 '\0',需要手动处理字符串连接 char *strcat(char *dest, const char *src); char *strncat(char *dest, const char *src, size_t n); // 确保目标缓冲区足够大字符串比较 int strcmp(const char *s1, const char *s2); int strncmp(const char *s1, const char *s2, size_t n); // 返回值:0表示相等,<0表示s1<s2,>0表示s1>s2字符串查找 char *strchr(const char *str, int c); // 查找字符首次出现 char *strrchr(const char *str, int c); // 查找字符最后出现 char *strstr(const char *haystack, const char *needle); // 查找子串字符串分割 char *strtok(char *str, const char *delim); // 注意:strtok 会修改原字符串,且不是线程安全的安全版本(C11) errno_t strcpy_s(char *dest, rsize_t destsz, const char *src); errno_t strcat_s(char *dest, rsize_t destsz, const char *src);最佳实践:缓冲区溢出防护 // 不安全 strcpy(dest, src); // 安全方式 strncpy(dest, src, sizeof(dest) - 1); dest[sizeof(dest) - 1] = '\0';字符串拼接安全 char buffer[100]; snprintf(buffer, sizeof(buffer), "%s%s", str1, str2);动态字符串处理 char *safe_strdup(const char *str) { if (!str) return NULL; size_t len = strlen(str) + 1; char *copy = malloc(len); if (copy) memcpy(copy, str, len); return copy; }字符串格式化 char buffer[256]; int result = snprintf(buffer, sizeof(buffer), "Value: %d", value); if (result < 0 || result >= sizeof(buffer)) { // 处理错误 }常见陷阱:忘记为 '\0' 预留空间使用未初始化的字符串混淆 strlen 和 sizeof忽略函数返回值多次调用 strtok 时的状态问题
阅读 0·2月18日 17:21

C语言中预处理器指令的完整列表和使用场景有哪些?

C语言中预处理器指令的完整列表和使用场景有哪些?核心预处理器指令:文件包含 #include #include <stdio.h> // 系统头文件 #include "myheader.h" // 用户头文件 // 条件包含 #if defined(USE_FEATURE) #include "feature.h" #endif宏定义 #define // 简单宏 #define PI 3.14159 #define MAX_SIZE 100 // 带参数的宏 #define SQUARE(x) ((x) * (x)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) // 字符串化 #define STR(x) #x #define PRINT_VAR(var) printf(#var " = %d\n", var) // 连接 #define CONCAT(a, b) a##b条件编译 #if defined(UNIX) #include <unistd.h> #elif defined(WINDOWS) #include <windows.h> #else #error "Unsupported platform" #endif #ifdef DEBUG #define LOG(x) printf x #else #define LOG(x) #endif错误和警告 #if SIZE < 0 #error "Size must be positive" #endif #if !defined(VERSION) #warning "VERSION not defined, using default" #define VERSION "1.0" #endif行控制 #line #line 100 "custom.c" // 错误信息将显示为 custom.c:100编译指示 #pragma #pragma once // 防止重复包含 #pragma pack(1) // 内存对齐 #pragma warning(disable:4996) // 禁用警告取消定义 #undef #define TEMP 100 #undef TEMP高级应用场景:跨平台兼容性 #if defined(_WIN32) || defined(_WIN64) #define PATH_SEPARATOR '\\' #else #define PATH_SEPARATOR '/' #endif调试和日志 #ifdef DEBUG #define DEBUG_PRINT(fmt, ...) printf(fmt, ##__VA_ARGS__) #else #define DEBUG_PRINT(fmt, ...) #endif版本控制 #define VERSION_MAJOR 2 #define VERSION_MINOR 5 #define VERSION_STRING "2.5"注意事项:宏没有类型检查宏展开可能导致意外的副作用优先使用 const 和 inline 函数替代宏
阅读 0·2月18日 17:21

C语言中预定义宏和条件编译的完整用法是什么?

C语言中预定义宏和条件编译的完整用法是什么?预定义宏:标准预定义宏 void print_predefined_macros() { printf("File: %s\n", __FILE__); printf("Line: %d\n", __LINE__); printf("Date: %s\n", __DATE__); printf("Time: %s\n", __TIME__); printf("Function: %s\n", __func__); #ifdef __STDC_VERSION__ printf("C Standard: %ld\n", __STDC_VERSION__); #endif }编译器特定宏 void compiler_specific_code() { #ifdef __GNUC__ printf("GCC compiler\n"); #elif defined(__clang__) printf("Clang compiler\n"); #elif defined(_MSC_VER) printf("MSVC compiler\n"); #endif }平台检测 void platform_specific_code() { #ifdef _WIN32 printf("Windows platform\n"); #elif defined(__linux__) printf("Linux platform\n"); #elif defined(__APPLE__) printf("macOS platform\n"); #endif }条件编译:基本条件编译 #ifdef DEBUG #define LOG(x) printf x #else #define LOG(x) #endif void function() { LOG(("Debug message\n")); }多重条件 #if defined(UNIX) && !defined(DEBUG) #define OPTIMIZED_CODE #endif #if VERSION >= 2 #include "new_features.h" #else #include "legacy_features.h" #endif错误和警告 #if SIZE < 0 #error "Size must be positive" #endif #if !defined(VERSION) #warning "VERSION not defined, using default" #define VERSION "1.0" #endif高级用法:宏字符串化 #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) printf("Line: %s\n", TOSTRING(__LINE__));宏连接 #define CONCAT(a, b) a##b int CONCAT(var, 1) = 10; // var1可变参数宏 #define LOG(fmt, ...) printf("[LOG] " fmt "\n", ##__VA_ARGS__) LOG("Value: %d", 42); LOG("Simple message");实际应用:调试宏 #ifdef DEBUG #define DEBUG_PRINT(fmt, ...) \ printf("[DEBUG %s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) #else #define DEBUG_PRINT(fmt, ...) #endif void example_function() { DEBUG_PRINT("Processing data: %d", 100); }版本控制 #define VERSION_MAJOR 2 #define VERSION_MINOR 5 #define VERSION_PATCH 1 #define VERSION_STRING \ TOSTRING(VERSION_MAJOR) "." \ TOSTRING(VERSION_MINOR) "." \ TOSTRING(VERSION_PATCH) printf("Version: %s\n", VERSION_STRING);跨平台代码 #ifdef _WIN32 #define PATH_SEPARATOR '\\' #define PATH_SEPARATOR_STR "\\" #else #define PATH_SEPARATOR '/' #define PATH_SEPARATOR_STR "/" #endif void join_path(char *dest, const char *dir, const char *file) { sprintf(dest, "%s%s%s", dir, PATH_SEPARATOR_STR, file); }功能开关 #define FEATURE_A_ENABLED 1 #define FEATURE_B_ENABLED 0 void process_data() { #if FEATURE_A_ENABLED feature_a_process(); #endif #if FEATURE_B_ENABLED feature_b_process(); #endif }最佳实践:头文件保护 #ifndef HEADER_H #define HEADER_H // 头文件内容 #endif一次性包含 #pragma once // 头文件内容宏作用域控制 #undef TEMP_MACRO #define TEMP_MACRO(x) (x * 2) int result = TEMP_MACRO(5); #undef TEMP_MACRO注意事项:宏的副作用 #define SQUARE(x) ((x) * (x)) int i = 2; int result = SQUARE(i++); // 未定义行为宏的括号 #define MUL(a, b) ((a) * (b)) int result = MUL(2 + 3, 4); // 正确: (2 + 3) * 4 = 20条件编译的嵌套 #ifdef DEBUG #ifdef VERBOSE #define LOG(x) printf x #else #define LOG(x) #endif #else #define LOG(x) #endif
阅读 0·2月18日 17:21