作者:张裕鹏 日期:2021-5-11

1. 内存对齐导致的错误

内存对齐在 C 语言基础考试的时候经常会考到,其实很多人只是知道这个概念,但是并不清楚在实际中会有什么应用,下面给一个例子来进行说明。
常见的内存对齐一般出现在结构体中,如下

  1. typedef struct C2C_AV_TRANS_FIXED_HEADER_{
  2. unsigned int request_id;
  3. unsigned long long int time_ms;
  4. int extension_length;
  5. }C2C_AV_TRANS_FIXED_HEADER;

该结构体的大小为:24 Byte 。如果这个都不理解,可以看看这篇文档:如何理解 struct 的内存对齐?
上面的结构体是一个媒体文件头,那在通过网络传输过来之后(都是 char 类型),想知道 extension_length 的内容是多少,该如何获取呢?可以看看下面代码

  1. int main()
  2. {
  3. C2C_AV_TRANS_FIXED_HEADER c;
  4. c.request_id = 123;
  5. c.time_ms = 456;
  6. c.extension_length = 789;
  7. char *buf = (char *)malloc(100);
  8. if(buf == NULL){
  9. printf("malloc failed !\n");
  10. return -1;
  11. }
  12. memcpy(buf, &c, sizeof(C2C_AV_TRANS_FIXED_HEADER));
  13. int length = *(int*)(buf+16);
  14. printf("length:%d\n", length);
  15. return 0;
  16. }

结果如下:length:789
这边要特别注意代码:int length = *(int*)(buf+16)

  1. 这边将 buf 内容先偏移 16 字节(因为 buf 的类型为 char * 类型,所以可以直接 +16);
  2. 然后再将类型转换为(int *);
  3. 最后再解引用;

这块内容经常会写错,比如写成:int length = (int)*(buf+16),需要特别注意!

2. 强制类型转换导致的错误

对于强制类型转换如果理解不足,经常会导致莫名的错误,下面介绍一种由于强制类型转换导致的程序崩溃。

  1. void change(int *num)
  2. {
  3. *num = 256;
  4. }
  5. int main()
  6. {
  7. short a = 0;
  8. change(&a);
  9. printf("a: %d\n", a);
  10. return 0;
  11. }

上面的程序会导致程序崩溃,主要的原因是 short 只有 2 个字节,而 int 有 4 个字节,所以将 a 的地址传入之后,chang 函数会将该指针认为是 int * 类型,导致使用的时候使用了 4 个字节,造成了栈溢出,导致了崩溃。
所以在写代码的时候一定要避免类似这样的错误,因为有时候这个看起来不明显。