queries about sprintf

J

jimjim

Hello,

I was wondering about the implications of giving as an argument to sprintf a
different data type from the one specified in the format argument. This type
of question along with some others are asked below:

1. #include <stdio.h>

int main(){
char buffer[20];
int j, t;

t = sprintf(buffer," %c ", 97 );

printf("char a in decimal is: %d\n\n", 'a');
printf("sprintf returns: %d \n", t);
for(j=0;j<t;j++)
printf("This is buffer[%d] == %d \n", j, buffer[j]);

return 0;}

Output:
char a in decimal is: 97

sprintf returns: 3
This is buffer[0] == 32
This is buffer[1] == 97
This is buffer[2] == 32

Why does sprintf return 3 and not 1?
On my machine, every ASCII character is essentially an one-byte integer
number. In this case, I would expect that integer 97, which maps to 'a',
would be stored to the byte buffer[0]. Instead, buffer[0] stores 32 which is
the space character!

2. In the above program, I changed the one statement that now reads:
t = sprintf(buffer," %c ", 300 );

buffer[1] is not 300, which I find reasonable as a signed char stores values
from -128 to +127. My question is why is it possible to store a value in
excess of +127 (or +255 for unsigned char), without receiving a warning
like: "overflow in implicit constant conversion ". (compiled with gcc 3. ...
.. ... and -Wall)

3. In the above program, I changed two statements that now read:
t = sprintf(buffer," %d ", 'a' );
printf("This is buffer[%d] == %c \n", j, buffer[j]);

Output:
char a in decimal is: 97

sprintf returns: 4
This is buffer[0] ==
This is buffer[1] == 9
This is buffer[2] == 7
This is buffer[3] ==

I can see that each digit of the integer 97 (character a) is stored to
different bytes in the buffer. Can you explain this behaviour please?

4. In the above program, I changed one statement that now reads:
t = sprintf(buffer," %d ", "hello" );

What happens in this case?


I have read the manual page regarding stdarg -- variable argument lists @
http://www.freebsd.org/cgi/man.cgi?...ropos=0&manpath=FreeBSD+5.4-RELEASE+and+Ports
However, it is still tough for me to read through the C library's
implementation of the sprintf. Answers to my questions with references to
the C library's implementation of the sprintf are more than wellcome.

TIA
 
B

Barry Schwarz

Hello,

I was wondering about the implications of giving as an argument to sprintf a
different data type from the one specified in the format argument. This type
of question along with some others are asked below:

Look in your reference for the default promotions that are
automatically performed on the arguments of a call to a variadic
function.
1. #include <stdio.h>

int main(){
char buffer[20];
int j, t;

t = sprintf(buffer," %c ", 97 );

printf("char a in decimal is: %d\n\n", 'a');
printf("sprintf returns: %d \n", t);
for(j=0;j<t;j++)
printf("This is buffer[%d] == %d \n", j, buffer[j]);

return 0;}

Output:
char a in decimal is: 97

sprintf returns: 3
This is buffer[0] == 32
This is buffer[1] == 97
This is buffer[2] == 32

Why does sprintf return 3 and not 1?

What is the meaning of the value returned by sprintf? Are you
confusing it with the value returned by sscanf?
On my machine, every ASCII character is essentially an one-byte integer
number. In this case, I would expect that integer 97, which maps to 'a',
would be stored to the byte buffer[0]. Instead, buffer[0] stores 32 which is
the space character!

Look at your format string in the call to sprintf. What is the first
character you specified to be stored in buffer? In which element of
buffer should this character be stored?
2. In the above program, I changed the one statement that now reads:
t = sprintf(buffer," %c ", 300 );

buffer[1] is not 300, which I find reasonable as a signed char stores values
from -128 to +127. My question is why is it possible to store a value in
excess of +127 (or +255 for unsigned char), without receiving a warning
like: "overflow in implicit constant conversion ". (compiled with gcc 3. ...
. ... and -Wall)

Because the C language is designed for people who know what they are
doing and does not try to second guess the programmer's intent. Cases
where the programmer violates this assumption are relegated to
"undefined behavior".
3. In the above program, I changed two statements that now read:
t = sprintf(buffer," %d ", 'a' );
printf("This is buffer[%d] == %c \n", j, buffer[j]);

Output:
char a in decimal is: 97

sprintf returns: 4
This is buffer[0] ==
This is buffer[1] == 9
This is buffer[2] == 7
This is buffer[3] ==

I can see that each digit of the integer 97 (character a) is stored to
different bytes in the buffer. Can you explain this behaviour please?

Buffer does not store digits. It stores characters. How many
characters can fit in a byte?
4. In the above program, I changed one statement that now reads:
t = sprintf(buffer," %d ", "hello" );

What happens in this case?

Undefined behavior. You told sprintf to expect an int and then gave
it a char*. How is sprintf to know you are lying or incompetent (or
maybe just experimenting)?
I have read the manual page regarding stdarg -- variable argument lists @
http://www.freebsd.org/cgi/man.cgi?...ropos=0&manpath=FreeBSD+5.4-RELEASE+and+Ports
However, it is still tough for me to read through the C library's
implementation of the sprintf. Answers to my questions with references to
the C library's implementation of the sprintf are more than wellcome.

Do not read any particular implementation or documentation unless you
are only interested in the behavior of that implementation. There are
pdf copies of the draft standard available on the web. That is the
definition of the language and the standard library functions.


<<Remove the del for email>>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,818
Latest member
Brigette36

Latest Threads

Top