C/C++函数传递参数需要指定缓冲区大小

!本文可能 超过1年没有更新,今后内容也许不会被维护或者支持,部分内容可能具有时效性,涉及技术细节或者软件使用方面,本人不保证相应的兼容和可操作性。

原文发表于2009年2月5日 标题是《一个自己犯的C/C++错误》

以前自己写程序时经常犯的错误,后来才开始重视起来,为了更好的说明这个错误,我将演示代码贴出来:

#include <stdio.h> 
#include <string.h> 
#include <memory.h> 
 
// 写出缓冲区的16进制值
void print_byte(void *ptr, size_t size)
{
  unsigned i;
  unsigned char *bptr = (unsigned char *)ptr;
 
  for(i = 0; i < size; i++) {
    printf("%x ", *(bptr + i));
  }
  putchar('\n');
}
 
// 测试函数1 
void func_test(char *pbuf, size_t size)
{
  printf("SIZE=%d ? \n", sizeof(pbuf));
  memset(pbuf, 0, sizeof(pbuf));  // 我以前经常犯的错误 
  print_byte(pbuf, size);
}
 
// 测试函数2 
void func_test1(char *pbuf, size_t size)
{
  memset(pbuf, 0, size);
  print_byte(pbuf, size);
}
 
int main(void)
{
  char buffer[] = "0123456789";  // 字符缓冲区 
 
  printf("SIZE=%d\n", sizeof(buffer));
  print_byte(buffer, sizeof(buffer));
  memset(buffer, 0, sizeof(buffer));
  print_byte(buffer, sizeof(buffer));
 
  strcpy(buffer, "0123456789");
  func_test(buffer, sizeof(buffer));
  func_test1(buffer, sizeof(buffer));
 
  return 0;
}

可以看出,表面上这个错误是关于在函数内部将传参指向的缓冲区清零的,调试上述程序后发现主函数里定义的缓冲区被全部成功设置为0,而将这个缓冲区地址传入函数func_test后只有前4个字节被置0,那么问题出在哪里呢?问题就在sizeof上,在主函数上sizeof算得缓冲区为11(包含字符串结尾\0),而函数func_test里算得是4,很明显只是计算的指针的大小。

疑惑就在这里,buffer是数组名不就是地址吗,为什么传参后sizeof值就不算整个数组的大小而只算指针的大小呢?

其实这个问题很容易buffer是数组名,sizeof(数组名)算得的是整个数组占用的字节数,一旦赋值给任何指针(函数传参也相当于一种赋值),也就算的是这个指针的占用空间,和数组就没任何关系了。若还是算的事数组占用空间,那这个指针的占用就没办法计算了。

理解了这些就不难理解一些SDK提供的接口为什么要你传入缓冲区地址后还要你给出大小了,就像上面的修正函数func_test1。

通过这件事我知道什么事都不能想当然。不过对我过去的代码影响不是很大的因为在Windows API下经常使用固定大小MAX_PATH。于是大小就这样算了sizeof(TCHAR) * MAX_PATH。

若无特别说明,本网站文章均为原创,原则上这些文章不允许转载,但是如果阁下是出于研究学习目的可以转载到阁下的个人博客或者主页,转载遵循创作共同性“署名-非商业性使用-相同方式共享”原则,请转载时注明作者出处谢绝商业性、非署名、采集站、垃圾站或者纯粹为了流量的转载。谢谢合作!
请稍后...

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*