1756751 Members
2861 Online
108852 Solutions
New Discussion юеВ

Re: Simple C question

 
SOLVED
Go to solution
Joel Shank
Valued Contributor

Simple C question

I have been away from C programming for quite a while and am trying to figure out why I get the folowing results:

long long val;
char c_string[10];
val = 15422720;
sprintf(c_string, "%06x", val);
printf ("Output1: %s\n", c_string);
printf ("Output2: %06x\n", val);

The output I get is:

Output1: eb5500
Output2: 000002

In fact, when I go thru a loop changing val, Output1 changes correctly, but Output2 remains 00002.

I am sure this is going to be something stupid I am doing or not doing, but I need some help.

Thanks in advance,
jls
11 REPLIES 11
Hein van den Heuvel
Honored Contributor
Solution

Re: Simple C question

Which C compiler?
I think you simplied the example (which is good) beyond the point of there being a problem (which is bad).
I tossed a main(){ .. } around it and it prints the same numbers.
There is of course a warning about the format/variable mismatch.

$ cc --version
cc: HP C/aC++ B3910B A.06.14 [Feb 22 2007]
$ ./a.out
Output1: eb5500
Output2: eb5500

Good luck,
Hein.

James R. Ferguson
Acclaimed Contributor

Re: Simple C question

Hi Joel:

Interesting. I used an earlier compiler than Hein:

B3901BA B.11.11.16 HP C/ANSI C Developer's Bundle for HP-UX (S800)

# what /opt/ansic/bin/cc
/opt/ansic/bin/cc:
$Revision: 92453-07 linker linker crt0.o B.11.53 060807 $
LINT B.11.X.36086-36089-36092.GP CXREF B.11.X.36086-36089-36092.GP
HP92453-01 B.11.X.36086-36089-36092.GP HP C Compiler
$ PATCH/11.00:PHCO_27774 Oct 3 2002 09:45:59 $

Using the above I see:

# ./a.out
Output1: eb5500
Output2: 000082

...and using gcc on a Linux box:

$ gcc --version
$ gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-33)
$ ./a.out
Output1: eb5500
Output2: eb5500

Regards!

...JRF...
Joel Shank
Valued Contributor

Re: Simple C question

Yes it is very interesting! I know I am using an older version compiler:
B3901BA B.11.11.10HP C/ANSI C Developer's Bundle for HP-UX 11.i (S800)

and my what string is
# what /usr/bin/cc
/usr/bin/cc:
$Revision: 92453-07 linker linker crt0.o B.11.47 051104 $
LINT B.11.X.35098-35101.GP CXREF B.11.X.35098-35101.GP
HP92453-01 B.11.X.35098-35101.GP HP C Compiler
$ PATCH/11.00:PHCO_27774 Oct 3 2002 09:45:59 $

Since James can reproduce my results using an older compiler, I guess I'll just have to assume this is a "feature" of the past. I have access to newer compilers on other servers that I can use; but since I have a work-around, and am now aware of this "feature", I can live with it. I thought that printf and sprintf used the same underlying code and so assumed that results should have been the same. Guess I was wrong.

Thanks for your quick response and testing. It was greatly appreciated!

jls
Steven Schweda
Honored Contributor

Re: Simple C question

alp $ type lame1.c
#include

int main( void)
{
long long val;
char c_string[10];
val = 15422720;
sprintf(c_string, "%06x", val);
printf ("Output1: %s\n", c_string);
printf ("Output2: %06x\n", val);
}

alp $ cc lame1

sprintf(c_string, "%06x", val);
..........................^
%CC-W-OUTTYPELEN, In this statement, this
argument to sprintf is of "a signed long
long" type and is not appropriate for the
conversion specifier "%06x". The value might
be truncated or formatted in an unintended
manner.
at line number 8 in file ALP$DKA0:[SMS]LAME1.C;1

printf ("Output2: %06x\n", val);
...........................^
%CC-W-OUTTYPELEN, In this statement, this
argument to printf is of "a signed long long"
type and is not appropriate for the
conversion specifier "%06x". The value might
be truncated or formatted in an unintended
manner.
at line number 10 in file ALP$DKA0:[SMS]LAME1.C;1

Of course, it still works here:

alp $ link lame1
%LINK-W-WRNERS, compilation warnings
in module LAME1 file ALP$DKA0:[SMS]LAME1.OBJ;1

alp $ run lame1
Output1: eb5500
Output2: eb5500

Little-endian systems tend to do better at
hiding problems like this than big-endian
systems. (And a good compiler tends to
reveal them.)

alp $ cc /vers
HP C V7.3-009 on OpenVMS Alpha V7.3-2

For fewer problems, you might try making a
couple of minor changes:

alp $ gdiff lame1.c lame2.c
8c8
< sprintf(c_string, "%06x", val);
---
> sprintf(c_string, "%06llx", val);
10c10
< printf ("Output2: %06x\n", val);
---
> printf ("Output2: %06llx\n", val);
Joel Shank
Valued Contributor

Re: Simple C question

I must have the sloooooooowest internet connection known to man! How frustrating!

Thanks for your help :-)

jls
Steven Schweda
Honored Contributor

Re: Simple C question

For the record, on a PA-RISC (big-endian)
system (with an uninformative compiler):

td192> cc -o lame1 lame1.c

td192> cc -o lame2 lame2.c

td192> ./lame1
Output1: eb5500
Output2: 000082

td192> ./lame2
Output1: eb5500
Output2: eb5500

td192> cc -o lame2 lame2.c -V
cpp.ansi: HP92453-01 B.11.X.35175-35176.GP HP C Preprocessor (ANSI)
ccom: HP92453-01 B.11.X.36086-36089-36092.GP HP C Compiler
/usr/ccs/bin/ld: 92453-07 linker linker ld B.11.60 070209

antinode@td192> uname -a
HP-UX td192 B.11.11 U 9000/800 1839940656 unlimited-user license


While on an Itanium (little-endian) system
(with an informative compiler):

td176> cc -o lame1_i lame1.c
"lame1.c", line 8: warning #2181-D: argument is incompatible with
corresponding format string conversion
sprintf(c_string, "%06x", val);
^

"lame1.c", line 10: warning #2181-D: argument is incompatible with
corresponding format string conversion
printf ("Output2: %06x\n", val);
^

td176> cc -o lame2_i lame2.c

td176> ./lame1_i
Output1: eb5500
Output2: eb5500

td176> ./lame2_i
Output1: eb5500
Output2: eb5500

td176> cc -V
cc: HP aC++/ANSI C B3910B A.06.10 [Mar 22 2006]

td176> uname -a
HP-UX td176 B.11.23 U ia64 1928826293 unlimited-user license


Similarly, on a Solaris SPARC (big-endian)
system (with another unhelpful compiler):

ra# cc -o lame1 lame1.c

ra# cc -o lame2 lame2.c

ra# ./lame1
Output1: 000000
Output2: 000000

ra# ./lame2
Output1: eb5500
Output2: eb5500

At least here they're consistent.

ra# cc -V
cc: Sun C 5.8 2005/10/13

ra# uname -a
SunOS ra 5.10 Generic_120011-14 sun4u sparc SUNW,UltraSPARC-IIi-cEngine

The previously shown VMS Alpha system is, of
course, little-endian.

Note that in each case, the code without the
bugs (lame2.c) works properly.

> I thought that printf and sprintf used the
> same underlying code and so assumed that
> results should have been the same.

Used properly, they're probably consistent.
Used improperly, who can say?

> Guess I was wrong.

In so many ways.
Dennis Handly
Acclaimed Contributor

Re: Simple C question

You should be compiling on IPF and making that warning a hard error. +We2181 :-)

The solution and the reason is simple.
As Steven says, you need %llx.
The cause is because 64 bit values are split into even/odd registers for the first 4 parms, with possibly leaving a gap.
Your sprintf call just happens to align properly.

>Hein: it prints the same numbers.

Because IPF is a 64 bit machine. While PA2.0 is a 64 bit machine, the default +DD32 must match the previous calling conventions to maintain binary compatibility.

>JRF: I used an earlier compiler than Hein:

You're confused. You used a completely different compiler, on a different architecture. Only using +DD64 would "work".

>I guess I'll just have to assume this is a "feature" of the past.

No. It is a "feature" of the PA32 Procedure Calling Convention.

>but since I have a work-around, and am now aware of this "feature"

There is NO workaround, there is the correct format.

>I thought that printf and sprintf used the same underlying code and so assumed that results should have been the same.

That's not where the problem lies. It has to do with the PPC and even/odd matching.

>Steven: sprintf(c_string, "%06llx", val);

Exactly, %llx is the correct C99 format.

Dennis Handly
Acclaimed Contributor

Re: Simple C question

If you would like to get the warnings that Hein and Steven mentioned, you can download cadvise for free and run on your PA-RISC system:
http://www.hp.com/go/cadvise
Joel Shank
Valued Contributor

Re: Simple C question

I had to reopen this thread to give points to Dennis' reply which totally explained to me what was happening and why.

I love learning :-)