问题描述
|
我对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,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);
}
}
解决方法
对于
%d
:
sprintf(str,\"%d\",val);
ѭ8指向什么?如果之前有一个“ 9”,则它指向格式参数之一,否则它未初始化-在两种情况下,它都指向一个无效的写入位置。您需要另一个临时缓冲区将值写入其中。您很幸运案例1和案例2成功了。
,看一下这段代码:
if( fmt[i]==\'i\' || fmt[i]==\'d\' )
{
val=va_arg(ap,int);
sprintf(str,val);
strcat(tempBuf,str);
}
那里的sprintf()调用试图将内容写入ѭ8something。什么是str?
当您将其命名为ѭ12call时,str
将成为参数2.,字符串“ Hi There \”。您无法在C中更改字符串文字,这可能会失败并可能导致崩溃。
当您像myPrintf(\"%s %d\",tempbuf,24)
这样称呼它时,str
将是tmpbuf
,这是一个数组,您可以对其进行写入,这样就可以了。尽管它只保留9个字节的空间,所以很容易溢出该缓冲区。
你应该做一些类似的事情
char tmp[32];
sprintf(tmp,tmp);
,我会弯腰...在情况3的格式字符串后面加上逗号。