对于函数:void foo(char (*argv1)[3], char *argv2[3]) 来说:

  • char (*argv1)[3] 是数组的指针,编译器知道数组的大小
  • char *argv2[3] 是指针的数组,编译器不知道数组的大小,会退化为 char **argv2

如图所示:
数组 - 图1

  1. void foo(char (*argv1)[3], char *argv2[3])
  2. {
  3. sizeof(argv1); // 8
  4. sizeof(argv2); // 8
  5. sizeof(*argv1); // 3
  6. sizeof(*argv2); // 8
  7. }

char (*)[3] 是一种类型:

  1. typedef char (*arr_3_ptr_t)[3];

这种类型可以用于传递一些定长数组,例如:

  1. #define JMP_INS_SIZE 5
  2. typedef unsigned char ins_backup_t[JMP_INS_SIZE];
  3. /**
  4. * @brief 动态打桩函数
  5. * @param [in]old_func 需要被替换的函数
  6. * @param [in]new_func 要替换成什么函数
  7. * @param [out]buff 备份原函数入口处的指令
  8. */
  9. void stub(void* old_func, void* new_func, ins_backup_t *backup)
  10. {
  11. /// ...
  12. memcpy(*backup, olf_func, sizeof(*backup));
  13. /// ...
  14. }
  15. int main()
  16. {
  17. ins_backup_t malloc_backup;
  18. stub(malloc, my_malloc, &malloc_backup);
  19. }

使用typedef struct acc acc_t[1] 的好处

这就是数组的两头都占好的特性吧,定义时候能直接分配好地址,使用的时候还能把数组名当指针用。
对比:

  1. typedef struct acc acc_t[1]
  2. void foo(struct acc*);
  3. // 1. 使用原始写法
  4. struct acc acc1;
  5. foo(&acc);
  6. // 2. 使用这个技巧
  7. acc_t acc2;
  8. foo(acc2);

数组的一个坑

  1. int main()
  2. {
  3. int acc[1];
  4. printf("%d\n", acc);
  5. printf("%d\n", &acc);
  6. }
  7. // 结果相同:
  8. -42946092
  9. -42946092

就你妈离谱