printf() behavior

M

Mark

Hello,

this code produces warnings, but I want to understand how it's interpreted
by compiler.

#include <stdio.h>
int main(void)
{
int b;

b = (int)"hello"; /* 1 */

printf("%d\n", 3.2); /* 2 */

printf("%s\n", 1234); /* 3 */
printf("%s\n", b); /* 4 */

return 0;
}

Is the first statement legitimate? Am I right that in "1" b is evaluated to
address of string literal?
But I don't understand how can the compiler take the 2nd, 3rd and 4th
expressions?
 
I

Ian Collins

Hello,

this code produces warnings, but I want to understand how it's
interpreted by compiler.

#include <stdio.h>
int main(void)
{
int b;

b = (int)"hello"; /* 1 */

printf("%d\n", 3.2); /* 2 */

printf("%s\n", 1234); /* 3 */
printf("%s\n", b); /* 4 */

return 0;
}

Is the first statement legitimate? Am I right that in "1" b is evaluated
to address of string literal?

If an address will fit in an int. This will fail on most common 64 bit
systems.
But I don't understand how can the compiler take the 2nd, 3rd and 4th
expressions?

The parameters following the format string in printf are just values on
the stack (assuming there is one). They are not interpreted at compile
time, only when the program is run. Some compilers will check the
parameter types with the format string (gcc for example), but they are
not required to.
 
J

Jorgen Grahn

If an address will fit in an int. This will fail on most common 64 bit
systems.


The parameters following the format string in printf are just values on
the stack (assuming there is one). They are not interpreted at compile
time, only when the program is run. Some compilers will check the
parameter types with the format string (gcc for example), but they are
not required to.

And if you have such a compiler, it's wise to enable that warning, and
also enable it for home-made printf-style functions[1].

When I enabled it on old code, plenty of bugs showed up. Some
harmless, some definitely not. And often these things are used in
error handling -- code which does not get exercised that often, and
which must work.

/Jorgen

[1] At least with gcc, if you build your own functions on vsprintf()
and friends, there's an __attribute__ so you can say "this
function takes printf-style arguments beginning with #3" or
similar.
 
M

Malcolm McLean

If an address will fit in an int.  This will fail on most common 64 bit
systems.
However the campaign for 64 bit ints is working to change that
situation.

We've got a nice new slogan 'integers for all', making that point
that, with world population about 6 billion, if int is 32 bits some
people will have to do without.
 
I

Ian Collins

However the campaign for 64 bit ints is working to change that
situation.

We've got a nice new slogan 'integers for all', making that point
that, with world population about 6 billion, if int is 32 bits some
people will have to do without.

Just like IPv4 addresses? Although the campaign for IPv6 has a little
more momentum than yours.
 
F

Felix Palmen

* Malcolm McLean said:
However the campaign for 64 bit ints is working to change that
situation.

We've got a nice new slogan 'integers for all', making that point
that, with world population about 6 billion, if int is 32 bits some
people will have to do without.

Hmm. Actually, I'm happy with NOT being a number :)

But apart from that, I'd find it quite intuitive if an "int"
corresponded to the CPU data register size of the platform, given that
doesn't violate the integer type constraints of the standard...

Regards, Felix
 
K

Kenny McCormack

However the campaign for 64 bit ints is working to change that
situation.

We've got a nice new slogan 'integers for all', making that point
that, with world population about 6 billion, if int is 32 bits some
people will have to do without.

(over) 7 billion.

Do try to keep up.

--
"The anti-regulation business ethos is based on the charmingly naive notion
that people will not do unspeakable things for money." - Dana Carpender

Quoted by Paul Ciszek (pciszek at panix dot com). But what I want to know
is why is this diet/low-carb food author doing making pithy political/economic
statements?

But the above quote is dead-on, because, the thing is - business in one
breath tells us they don't need to be regulated (that they can morally
self-regulate), then in the next breath tells us that corporations are
amoral entities which have no obligations to anyone except their officers
and shareholders, then in the next breath they tell us they don't need to be
regulated (that they can morally self-regulate) ...
 
N

Nobody

However the campaign for 64 bit ints is working to change that
situation.

So if "int", "long" and "long long" are all going to be 64 bits, is
"short" going to be 16 or 32 bits? Or are you going to make *that* 64 bits
as well for good measure?

64-bit "int" ain't gonna happen; it just breaks too much code. Even a
64-bit "long" broke too much stuff for Microsoft's liking, hence Win64
using a 32-bit "long".
 
M

Mark

pete said:
Is the first statement legitimate?

N869
6.3.2.3 Pointers

[#6] Any pointer type may be converted to an integer type.
Except as previously specified, the result is
implementation-defined. If the result cannot be represented
in the integer type, the behavior is undefined. The result
need not be in the range of values of any integer type.

Am I right that in "1" b is evaluated to
address of string literal?

No.

Then who is right, you or Ian Collins (see his answer up the thread) ?
 
M

Mark

Ian Collins said:
If an address will fit in an int. This will fail on most common 64 bit
systems.

Could you provide a snippet from the C standard sapecifying this?
The parameters following the format string in printf are just values on
the stack (assuming there is one). They are not interpreted at compile
time, only when the program is run. Some compilers will check the
parameter types with the format string (gcc for example), but they are not
required to.

But the standard doesn't address to such terms as 'stack', 'heap' and so on,
what does it say about these:

printf("%d\n", 3.2);
printf("%s\n", 1234);
printf("%s\n", b);

Are these under the 'implementation defined' behavior ?
 
K

Keith Thompson

Mark said:
But the standard doesn't address to such terms as 'stack', 'heap' and so on,
what does it say about these:

printf("%d\n", 3.2);
printf("%s\n", 1234);
printf("%s\n", b);

Are these under the 'implementation defined' behavior ?

No, they're undefined behavior.

The latest draft of the C standard is freely available at
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf>.
7.19.6.1p9 says:

If any argument is not the correct type for the corresponding
conversion specification, the behavior is undefined.
 
I

Ian Collins

Could you provide a snippet from the C standard sapecifying this?

No. But it's a general rule that quarts don't fit into pint pots.
But the standard doesn't address to such terms as 'stack', 'heap' and so
on, what does it say about these:

printf("%d\n", 3.2);
printf("%s\n", 1234);
printf("%s\n", b);

Are these under the 'implementation defined' behavior ?

No, they are undefined
 
B

Barry Schwarz

On Thu, 12 Aug 2010 13:16:30 +0900, "Mark"

snip
But the standard doesn't address to such terms as 'stack', 'heap' and so on,
what does it say about these:

printf("%d\n", 3.2);

The expression 3.2 has type double. %d requires the argument to be an
int. Paragraph 7.19.6.1-9 specifically states that the behavior in
this situation is undefined.
printf("%s\n", 1234);

The expression 1234 has type int. %s requires the argument to be a
pointer to char. Same paragraph applies.
printf("%s\n", b);

The object b has type int in the original post. Same as previous
statement.
Are these under the 'implementation defined' behavior ?

No, they are explicitly identified as undefined behavior.
 
B

Barry Schwarz

pete said:
Is the first statement legitimate?

N869
6.3.2.3 Pointers

[#6] Any pointer type may be converted to an integer type.
Except as previously specified, the result is
implementation-defined. If the result cannot be represented
in the integer type, the behavior is undefined. The result
need not be in the range of values of any integer type.

Am I right that in "1" b is evaluated to
address of string literal?

No.

Then who is right, you or Ian Collins (see his answer up the thread) ?

There is no conflict between the two.

In responding to the first question, both say possibly, providing
certain conditions are satisfied. The only difference is the
terminology used.

For the second question, b is an int and therefore does not hold any
address. Only pointers hold addresses. Since the conversion from
pointer to int is implementation-defined (6.3.2.3-6), a definitive
answer can be had only in relation to a specific implementation.
 
M

Malcolm McLean

So if "int", "long" and "long long" are all going to be 64 bits, is
"short" going to be 16 or 32 bits? Or are you going to make *that* 64 bits
as well for good measure?
When did you last use a short?

It's quite rare to need such a huge number of 16 bit integers that
memory is an issue. Lots of integers never go above 30,000, of course,
but almost always it is better to use int.

A C type should be thought of as a communications protocol between
functions. The fewer protocols you have, the less likely you are to
need to write 'glue" code switching from one type to another. Most
software that fails fails because of the complexity of integrating all
the different components, not because the program no longer fits in
machine memory.
 
I

Ian Collins

When did you last use a short?

About 10 minutes ago in my case (a network port number).
It's quite rare to need such a huge number of 16 bit integers that
memory is an issue. Lots of integers never go above 30,000, of course,
but almost always it is better to use int.

A C type should be thought of as a communications protocol between
functions. The fewer protocols you have, the less likely you are to
need to write 'glue" code switching from one type to another. Most
software that fails fails because of the complexity of integrating all
the different components, not because the program no longer fits in
machine memory.

That's why platforms have ABIs.

This 64 bit int argument has been done to death here more than once. It
is well established that 64 bit ints more often than not degrade
performance on most 64 bit systems in use today. Not to mention the
fact that 64 bit ABIs were set in stone many years ago and won't be
changing any time soon.

Perhaps you should wait for 128 bit systems and try again?
 
S

Sjouke Burry

Malcolm said:
When did you last use a short?

I even used char to store.
Example:
#define maxstars (924710)
static struct{
int x,y;
double ra;
double decl;
char col,t1,t2,t3;
int filelocation;
} s[maxstars];
 
N

Nobody

When did you last use a short?
Yesterday.

It's quite rare to need such a huge number of 16 bit integers that
memory is an issue.

Memory is always an issue. A lot of the code I write is in programs which
will end up having hundreds of concurrent instances.
 
B

Ben Bacarisse

Mark said:
Could you provide a snippet from the C standard sapecifying this?

6.3.2.3 p6:

"Any pointer type may be converted to an integer type. Except as
previously specified, the result is implementation-defined. If the
result cannot be represented in the integer type, the behavior is
undefined. The result need not be in the range of values of any
integer type."

and an example:

#include <stdio.h>

int main(void)
{
int x = (int)&x;
if ((int *)x != &x)
puts("Oh dear!");
return 0;
}

This prints "Oh dear!" on my system.

<snip>
 

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,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top