file-type

C语言sizeof函数详解:内存对齐与数据类型计算

DOC文件

下载需积分: 9 | 43KB | 更新于2024-09-11 | 68 浏览量 | 2 下载量 举报 2 收藏
download 立即下载
在C语言中,`sizeof()` 是一个非常重要的运算符,用于获取变量、类型或常量在内存中占用的字节数。这个运算符在编译时执行,而不是在运行时动态计算,因此它提供了一种静态检查内存需求的方法。理解`sizeof()` 的工作原理有助于优化代码并确保正确处理不同数据类型的内存布局。 首先,`sizeof()` 对于不同数据类型的结果是固定的,例如,一个`char` 占1字节,`int`占4字节。然而,当我们应用到复杂的数据结构,如结构体时,事情就变得有趣起来。C语言为了提高处理器效率,会进行字节对齐。这意味着结构体中的成员会在内存中按照特定的对齐方式存储,比如基本数据类型如`short`对齐于2字节,`int`对齐于4字节,以此类推。这种对齐是为了减少处理器在读写数据时的额外开销,因为连续的内存访问通常比非连续的访问更快。 在结构体`struct S1`的例子中,尽管`char`和`int`在逻辑上只需要5个字节,但编译器可能会在其后的地址上插入填充字节以满足对齐要求,导致实际的`sizeof(struct S1)`可能是8字节。在`struct S2`中,虽然成员顺序改变,但因为`int`仍占据4字节,而`char`依然需要对齐,所以结果依然是8字节,即使`char`后面仍有填充字节。 在实际编程中,使用`sizeof()`除了可以计算内存需求,还可以帮助避免潜在的内存溢出错误。例如,当动态分配内存时,可以预计算数组或结构体的大小,然后使用`malloc()`或`calloc()`进行分配,确保足够的空间。此外,了解`sizeof()`对于处理指针也很关键,因为指针本身通常占用固定大小的内存,不论它指向的是何种类型的对象。 总结来说,`sizeof()` 是C语言中不可或缺的工具,它帮助开发者理解内存分配的细节,尤其是在处理复杂数据结构时。通过理解和掌握字节对齐的概念,开发者能够编写更高效、更安全的代码,充分利用现代计算机的硬件特性。

相关推荐

filetype

以下程序在管道关闭后正常结束时输出B: 数据包接收不完整":Success的报错信息,应怎样修改:#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/time.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/wait.h> // CRC32 校验函数 (简化实现) unsigned int crc32(const char *data, size_t len) { unsigned int crc = 0xFFFFFFFF; for (size_t i = 0; i < len; i++) { crc ^= data[i]; for (int j = 0; j < 8; j++) { crc = (crc >> 1) ^ (0xEDB88320 & -(crc & 1)); } } return ~crc; } // 通信数据结构 typedef struct { size_t size; // 数据大小 struct timeval timestamp; // 毫秒级时间戳 unsigned int crc; // CRC校验值 char data[1024]; // 数据内容 } CommPacket; // 统计数据结构(共享内存) typedef struct { int total_send; int total_recv; int success_count; int fail_count; size_t total_bytes_sent; size_t total_bytes_recv; } Stats; void print_stats(Stats *stats) { printf("\n=== 通信统计结果 ===\n"); printf("发送次数: %d\n", stats->total_send); printf("接收次数: %d\n", stats->total_recv); printf("成功次数: %d\n", stats->success_count); printf("失败次数: %d\n", stats->fail_count); printf("发送总字节: %zu\n", stats->total_bytes_sent); printf("接收总字节: %zu\n", stats->total_bytes_recv); } // 完整写入函数 int write_full(int fd, const void *buf, size_t count) { size_t total = 0; const char *p = buf; while (total < count) { ssize_t n = write(fd, p + total, count - total); if (n <= 0) return -1; // 写入失败 total += n; } return 0; } // 完整读取函数 int read_full(int fd, void *buf, size_t count) { size_t total = 0; char *p = buf; while (total < count) { ssize_t n = read(fd, p + total, count - total); if (n <= 0) return -1; // 读取失败 total += n; } return 0; } int main() { int pipe_a2b[2], pipe_b2a[2]; pid_t pid; // 创建共享统计内存 Stats *shared_stats = mmap(NULL, sizeof(Stats), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); memset(shared_stats, 0, sizeof(Stats)); // 创建管道 if (pipe(pipe_a2b) || pipe(pipe_b2a)) { perror("管道创建失败"); exit(EXIT_FAILURE); } if ((pid = fork()) < 0) { perror("fork失败"); exit(EXIT_FAILURE); } if (pid == 0) { // 进程B(接收方) close(pipe_a2b[1]); // 关闭A->B写端 close(pipe_b2a[0]); // 关闭B->A读端 CommPacket packet; while (1) { // 完整接收数据包 if (read_full(pipe_a2b[0], &packet, sizeof(packet)) != 0) { perror("B: 数据包接收不完整"); break; } shared_stats->total_recv++; shared_stats->total_bytes_recv += packet.size; // 计算CRC并验证(仅校验有效数据) unsigned int calc_crc = crc32(packet.data, packet.size); int crc_valid = (calc_crc == packet.crc); // 打印接收信息(毫秒级时间戳) printf("%ld.%06ld秒: B从A接收了%zu字节数据,校验%s\n", packet.timestamp.tv_sec, packet.timestamp.tv_usec, packet.size, crc_valid ? "正确" : "错误"); // 完整发送响应 if (write_full(pipe_b2a[1], &crc_valid, sizeof(int)) != 0) { perror("B: 响应发送失败"); break; } // 更新统计 if (crc_valid) shared_stats->success_count++; else shared_stats->fail_count++; } close(pipe_a2b[0]); close(pipe_b2a[1]); exit(EXIT_SUCCESS); } else { // 进程A(发送方) close(pipe_a2b[0]); // 关闭A->B读端 close(pipe_b2a[1]); // 关闭B->A写端 // 测试数据 const char *test_data[] = { "Hello, this is first message", "Second transmission with data", "Third packet contents", "" }; for (int i = 0; i < 4; i++) { sleep(1); // 模拟时间间隔 // 准备数据包 CommPacket packet; strncpy(packet.data, test_data[i], sizeof(packet.data)); packet.size = strlen(test_data[i]); // 仅校验有效数据,不包括结束符 gettimeofday(&packet.timestamp, NULL); packet.crc = crc32(packet.data, packet.size); // 完整发送数据 if (write_full(pipe_a2b[1], &packet, sizeof(packet)) != 0) { perror("A: 数据发送失败"); break; } shared_stats->total_send++; shared_stats->total_bytes_sent += packet.size; // 打印发送信息(毫秒级时间戳) printf("%ld.%06ld秒: A发送了%zu字节数据给B\n", packet.timestamp.tv_sec, packet.timestamp.tv_usec, packet.size); // 完整接收响应 int crc_valid; if (read_full(pipe_b2a[0], &crc_valid, sizeof(int)) != 0) { perror("A: 响应接收失败"); break; } struct timeval now; gettimeofday(&now, NULL); printf("%ld.%06ld秒: A: B告诉我收到了%zu字节数据,校验%s\n", now.tv_sec, now.tv_usec, packet.size, crc_valid ? "正确" : "失败"); } // 关闭管道(触发B退出) close(pipe_a2b[1]); close(pipe_b2a[0]); wait(NULL); // 等待子进程结束 // 打印最终统计 print_stats(shared_stats); // 释放共享内存 munmap(shared_stats, sizeof(Stats)); } return 0; }

夏日捉虫
  • 粉丝: 23
上传资源 快速赚钱