具有可变长度参数的函数
我对 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);
}
}
I have following question on function with Variable length argument in C:
Case 1 (Works)
myPrintf("%d %s", 24, "Hi There");
Case 2 (Works)
char tempbuf[9]="Hi There";`
myPrintf("%s %d", tempbuf, 24)
Case 3 (Doesn't work)
myPrintf("%s %d", "Hi There", 24)
Does anyone has any idea why the case 3 doesn't work. I could see str = va_arg(ap, char *);
returning 24
for this case intead of the actual string.
Code for myPrintf:
(It is not fully functional though)
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);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
对于
%d
来说:str
指向什么?如果之前有一个%s
,它就指向格式参数之一,否则它是未初始化的——在这两种情况下,它都指向一个无效的写入位置。您需要另一个临时缓冲区来写入值。你很幸运,案例 1 和案例 2 都成功了。In the case for
%d
:what does
str
point to? If there was a%s
earlier, it points to one of the format arguments, otherwise it is uninitialized -- in both cases, it points to an invalid location for writing. You need another temporary buffer to write the value into. You were just lucky that cases 1 and 2 worked.看一下这段代码:
sprintf() 调用试图向
str
写入一些内容。什么是 str ?当您像
myPrintf("%s %d", "Hi There", 24)
那样调用它时,str
将是 2. 参数,即字符串“Hi There” ”。您无法更改 C 中的字符串文字,这可能会失败并可能导致崩溃。当您像
myPrintf("%s %d", tempbuf, 24)
那样调用它时,str
将是tmpbuf
,它是一个数组,你可以写信给它,这样就很好了。但它只保留 9 个字节的空间,因此很容易溢出该缓冲区。你应该做类似的事情
Take a look at this code:
The sprintf() call there is trying to write something to
str
. What is str ?When you call it like
myPrintf("%s %d", "Hi There", 24)
, thestr
will be the 2. argument, the string "Hi There". You cannot change a string literal in C, this will likely fail and might cause a crash.When you call it like
myPrintf("%s %d", tempbuf, 24)
,str
will betmpbuf
, which is an array, which you can write to so that's fine. It only holds room for 9 bytes though, so it's easy to overflow that buffer.You should rather just do something like
我会冒险...在情况 3 的格式字符串后面放置一个逗号。
I'll go out on a limb... Put a comma after the format string for case 3.