2

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

}

7
  • 2
    What's the code for myPrintf()? Commented May 24, 2011 at 15:57
  • 2
    We'll need to see the code for myPrintf to offer much help - it looks like a sensible code fragment so far. Commented May 24, 2011 at 15:57
  • Do you have any code for myprintf? Commented May 24, 2011 at 15:57
  • 1
    What's the difference between myPrintf and myprintf for that matter? Commented May 24, 2011 at 15:58
  • 2
    Are you sure you have the comma after the format string in case 3? Commented May 24, 2011 at 16:04

3 Answers 3

3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

@Punit: When %d is before %s, str is uninitialized -- you were just lucky it worked, it could have very well crashed. With %d after %s, when you used a character array for "Hi There", you could technically modify it because you allocated space for it. When you pass "Hi There" directly, it's a const string, so you can't write to it.
1

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

Comments

0

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

1 Comment

I'm guessing your real code is missing the comma: myPrintf("%s %d" "Hi There", 24); and the strings are getting concatenated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.