简体   繁体   中英

Function with Variable length argument

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);
}

}

In the case for %d :

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

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.

Take a look at this code:

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

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) , the str 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 be tmpbuf , 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

      char tmp[32];
      sprintf(tmp,"%d",val);
      strcat(tempBuf, tmp);

I'll go out on a limb... Put a comma after the format string for case 3.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM