具有可变长度参数的函数

时间:2011-05-24 15:53:45

标签: c

我在C:

中使用可变长度参数的函数有以下问题

案例1 (作品)

myPrintf("%d %s", 24, "Hi There");

案例2 (作品)

char tempbuf[9]="Hi There";`
myPrintf("%s %d", tempbuf, 24)

案例3 (没有工作)

myPrintf("%s %d", "Hi There", 24)

有谁知道为什么案例3不起作用。我可以看到str = va_arg(ap, char *);返回24这个实际字符串的内容。

myPrintf的代码: (虽然它没有完全发挥作用)

void myPrintf(char *fmt, ...)
{
int i,j,val,len;
char *str;
int len2;
va_list ap;
char tempBuf[128];

len=strlen(fmt);

memset(tempBuf,0,MAX_MSZ_LEN);

va_start(ap,fmt);

for(i=0; i<len; i++)
{
switch(fmt[i])
{
  case '%' :
  i++;
  if( fmt[i] == 's' )
  {
    str = va_arg(ap, char *);
    strcat(tempBuf, str);
  }
  else
    if( fmt[i]=='i' || fmt[i]=='d' )
    {
      val=va_arg(ap,int);
      sprintf(str,"%d",val);
      strcat(tempBuf, str);
    }
  default : 
  len2=strlen(tempBuf);
  tempBuf[len2]=fmt[i];
  }
}
va_end(ap);
}

}

3 个答案:

答案 0 :(得分:3)

对于%d

sprintf(str,"%d",val);

str指向什么?如果之前有%s,则它指向其中一个格式参数,否则它未初始化 - 在这两种情况下,它都指向无效的写入位置。您需要另一个临时缓冲区来将值写入。你很幸运,案例1和案例2都有效。

答案 1 :(得分:1)

看看这段代码:

   if( fmt[i]=='i' || fmt[i]=='d' )
    {
      val=va_arg(ap,int);
      sprintf(str,"%d",val);
      strcat(tempBuf, str);
    }

sprintf()调用尝试向str写入内容。什么是str? 当您将其称为myPrintf("%s %d", "Hi There", 24)时,str将是2.参数,字符串“Hi There”。您无法在C中更改字符串文字,这可能会失败并可能导致崩溃。

当您将其称为myPrintf("%s %d", tempbuf, 24)时,str将是tmpbuf,这是一个数组,您可以写入,这样就可以了。它只能容纳9个字节,所以很容易溢出缓冲区。

你应该做一些像

这样的事情
      char tmp[32];
      sprintf(tmp,"%d",val);
      strcat(tempBuf, tmp);

答案 2 :(得分:0)

我会出局...在案例3的格式字符串后面加一个逗号。