By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,247 Members | 1,273 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,247 IT Pros & Developers. It's quick & easy.

printf errrow ! same code differernt result between dev c++ and vc6.0

P: n/a
void show( char *s, ...) is a function seemd like prinf
code
--------------

#include <stdio.h>
#include <stdarg.h>

void show( char *s, ...)
{
va_list stage;
char *ps;
char pchar;
int pint;
double pdouble;
float pfloat;

va_start( stage, s);
{
while (*s)
{
switch (*s)
{
case '%':
{
s++;
switch (*s)
{
case 'f':
case 'F':
pdouble = va_arg(stage, float );
printf("%f", pdouble);
break;

case 'd':
case 'D':
pint = va_arg(stage, int );
printf("%d", pint);
break;
case 's':
case 'S':

ps = va_arg(stage, char* );
printf("%s", ps);
break;

case 'c':
case 'C':
pchar = va_arg(stage, char );
printf("%c", pchar);
break;

}
s++;
break;
}
default:
printf("%c",*s);
s++;
break;

}
}

}
}

int main()
{
int x =55;
char h ='a';
show("%c",h);
show("%c",h);
return 0;
}

---------------------------------------

under vc6.0 it can run well!

but under linux redhat7.x gcc error! win2k +dev c++ 4.98
errow !

case 'c':
case 'C':
pchar = va_arg(stage, char ); // here!!!
printf("%c", pchar);
break;
how to fix

Nov 14 '05 #1
Share this Question
Share on Google+
9 Replies


P: n/a
In article <d1**********@news.yaako.com>, <ch***********@hotmail.com> wrote:
:void show( char *s, ...) is a function seemd like prinf
:code

: va_list stage;

: pdouble = va_arg(stage, float );

: pchar = va_arg(stage, char );

gcc warns about two things:

va.c: In function `show':
va.c:26: warning: `float' is promoted to `double' when passed through `...'
va.c:26: warning: (so you should pass `double' not `float' to `va_arg')
va.c:46: warning: `char' is promoted to `int' when passed through `...'
If you fix those two things then gcc will run the code.

I would hazard a guess that va_arg() is using sizeof()
and you happened to get an unaligned access when you
told it the wrong size.
--
'The short version of what Walter said is "You have asked a question
which has no useful answer, please reconsider the nature of the
problem you wish to solve".' -- Tony Mantler
Nov 14 '05 #2

P: n/a
ch***********@hotmail.com wrote:
void show( char *s, ...) is a function seemd like prinf
code
--------------

#include <stdio.h>
#include <stdarg.h>

void show( char *s, ...)
{
va_list stage;
char *ps;
char pchar;
int pint;
double pdouble;
float pfloat;

va_start( stage, s);
{
while (*s)
{
switch (*s)
{
case '%':
{
s++;
switch (*s)
{
case 'f':
case 'F':
pdouble = va_arg(stage, float );
printf("%f", pdouble);
break;

case 'd':
case 'D':
pint = va_arg(stage, int );
printf("%d", pint);
break;
case 's':
case 'S':

ps = va_arg(stage, char* );
printf("%s", ps);
break;

case 'c':
case 'C':
pchar = va_arg(stage, char );
printf("%c", pchar);
break;
You need a default here, as you otherwise run into trouble
for the string "%"; after reading '%', you skip over
'\0' without a default label (or a check against *s!=0)...
}
s++;
.... and then step over the '\0' to point to the next character.
Note that this is still legal -- it is evaluating *s which
can bring you into the realm of undefined behaviour (can because
you may be lucky in that the underlying storage s points to is
greater than strlen(s)+1 bytes and one of these bytes is '\0').

For the issues with arguments of variadic functions and va_arg,
Walter's post cleared that up.
Cheers
Michael
break;
}
default:
printf("%c",*s);
s++;
break;

}
}

}
}

int main()
{
int x =55;
char h ='a';
show("%c",h);
show("%c",h);
return 0;
}

---------------------------------------

under vc6.0 it can run well!

but under linux redhat7.x gcc error! win2k +dev c++ 4.98
errow !

case 'c':
case 'C':
pchar = va_arg(stage, char ); // here!!!
printf("%c", pchar);
break;
how to fix

--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 14 '05 #3

P: n/a
ch***********@hotmail.com wrote:
[code snipped, see replacement below]
under vc6.0 it can run well!
It shouldn't.
but under linux redhat7.x gcc error! win2k +dev c++ 4.98
errow !
case 'c':
case 'C':
pchar = va_arg(stage, char ); // here!!!
printf("%c", pchar);
break;
how to fix


First turn your diagnostics on.

Your error is in not realizing that values are subject to default
promotions when passed to variadic functions. Try the following (my
changes are marked with /* mha ... */ comments):

/* mha: unused variables pfloat (in show) and x (in main) removed */

#include <stdio.h>
#include <stdarg.h>

void show(char *s, ...)
{
va_list stage;
char *ps;
char pchar;
int pint;
double pdouble;

va_start(stage, s);
{
while (*s)
switch (*s) {
case '%':
s++;
switch (*s) {
case 'f':
case 'F':
/* mha: because floats are promoted to doubles when
passed to variadic functions, the type in the next
line has been changed. */
pdouble = va_arg(stage, double /* was 'float' */ );
printf("%f", pdouble);
break;
case 'd':
case 'D':
pint = va_arg(stage, int);
printf("%d", pint);
break;
case 's':
case 'S':

ps = va_arg(stage, char *);
printf("%s", ps);
break;
/* mha: because chars are promoted to ints when
passed to variadic functions, the type in the next
line has been changed. */

case 'c':
case 'C':
pchar = va_arg(stage, int /* was 'char' */ );
printf("%c", pchar);
break;
}
s++;
break;
default:
printf("%c", *s);
s++;
break;

}
}
}

int main()
{
char h = 'a';
show("%c", h);
show("%c", h);
putchar('\n'); /* mha */
return 0;
}

Nov 14 '05 #4

P: n/a
put float to double
put char to int
why ?
before ask first question i fix the code like you
but i donot think it is right

i think sizeof (char ) != sizeof(int)
sizeof (float) != sizeof(double)

va_end(stage); // :) i lost it befor but i find the function still work
well, so .....

i want to read the printf() code!

can you post it? thank you
"pete" <pf*****@mindspring.com> ??????:42*********@mindspring.com...
ch***********@hotmail.com wrote:

void show( char *s, ...) is a function seemd like prinf
code
--------------

#include <stdio.h>
#include <stdarg.h>

void show( char *s, ...)
{
va_list stage;
char *ps;
char pchar;
int pint;
double pdouble;
float pfloat;

va_start( stage, s);


Where's va_end?
{


I don't like the extra braces.
It makes it harder to tell which switch is missing a default.
while (*s)
{
switch (*s)
{
case '%':
{
s++;
switch (*s)
{
case 'f':
case 'F':
pdouble = va_arg(stage, float );


Should be double instead of float.
printf("%f", pdouble);
break;

case 'd':
case 'D':
pint = va_arg(stage, int );
printf("%d", pint);
break;

case 's':
case 'S':

ps = va_arg(stage, char* );
printf("%s", ps);
break;

case 'c':
case 'C':
pchar = va_arg(stage, char );


Should be pint instead of pchar and int instead of char.
printf("%c", pchar);
break;

}
s++;
break;
}
default:
printf("%c",*s);
s++;
break;

}
}

}
}

int main()
{
int x =55;
char h ='a';
show("%c",h);
show("%c",h);
return 0;
}


/* BEGIN new.c */

#include <stdio.h>
#include <stdarg.h>

void show( char *s, ...)
{
va_list stage;
char *ps;
int pint;
double pdouble;

va_start( stage, s);
while (*s) {
switch (*s) {
case '%':
switch (*++s) {
case 'f':
case 'F':
pdouble = va_arg(stage, double);
printf("%f", pdouble);
break;
case 'd':
case 'D':
pint = va_arg(stage, int);
printf("%d", pint);
break;
case 's':
case 'S':
ps = va_arg(stage, char*);
printf("%s", ps);
break;
case 'c':
case 'C':
pint = va_arg(stage, int);
printf("%c", pint);
break;
default:
printf("%c", *s);
break;
}
break;
default:
printf("%c", *s);
break;
}
++s;
}
va_end(stage);
}

int main(void)
{
int x = 55;
char h = 'a';

show("%c", h);
show("%c", h);
putchar('\n');
show(
"%%f 9.0 is %f.\n%%d 9 is %d.\n"
"%%s nine is %s.\n%%c '9' is %c.\n",
9.0, 9, "nine", '9'
);
return 0;
}

/* END new.c */
--
pete

Nov 14 '05 #5

P: n/a
ch***********@hotmail.com wrote:
put float to double
put char to int
why ?
[Please keep some context of what you're replying to.]

The '...' arguments passed to variadic functions like printf are
undergo 'argument promotion'; float arguments are promoted to
double, char is generally promoted to int.
before ask first question i fix the code like you
but i donot think it is right

i think sizeof (char ) != sizeof(int)
sizeof (float) != sizeof(double)
This is irrelevant. You should learn C from a semantics point of
view, not from what or how a given machine implements C.
va_end(stage); // :) i lost it befor but i find the function
still work well, so .....
It may well work on your system, but the standard requires portable
programs to match each va_start with a corresponding va_end before
the function returns.

There have been systems where missing such a va_end will cause
problems.
i want to read the printf() code!

can you post it? thank you


Source code to printf is going to be different for each different
implementation. That said, just about every C development suite
these days comes with source code to the standard libraries.

For most, printf is implemented as a simple wrapper; it's usually
vprintf which does the hard work.

--
Peter

Nov 14 '05 #6

P: n/a
In article <d1**********@news.yaako.com>, <ch***********@hotmail.com> wrote:
:put float to double
:put char to int
:why ?
:before ask first question i fix the code like you
:but i donot think it is right

;i think sizeof (char ) != sizeof(int)
; sizeof (float) != sizeof(double)

Effectively when you use ... as a placeholder in the function prototype
to signal a use of varargs, you are not declaring the type of each individual
item, so the compiler has to fall back to the old K&R argument calling
conventions, as if you were calling a routine that had no prototype.
The old calling conventions automatically pass floats as doubles, and
pass char as int, and short as int, so that's the behaviour you inherit.
--
Are we *there* yet??
Nov 14 '05 #7

P: n/a
ch***********@hotmail.com wrote:

put float to double
put char to int
why ?
%c is supposed to take an int argument in a printf call.
printf("%f", pdouble);
%f takes a double argument in a printf call.
va_end(stage); // :) i lost it befor
but i find the function still work well, so .....
"Nothing quite encourages as does one's first unpunished crime."
http://fr.ebookslib.com/?a=sa&b=1089
i want to read the printf() code!

can you post it? thank you


min_printf is as far as I've gone
trying to code something like printf.

/* BEGIN min_printf.c */

#include <stdarg.h>
#include <stdio.h>
/*
** Only 5 features from stdio.h,
** are used in min_printf.c:
**
** 1 putc(c, stream)
** 2 stdout
** 3 FILE
** 4 EOF
** 5 int ferror(FILE *stream);
*/
#define put_c(c, stream) (putc((c), (stream)))
#define put_char(c) (put_c((c), stdout))
#define fsput_char(c) \
(put_char(c) == EOF && ferror(stdout) != 0 ? EOF : 1)

int min_printf(const char *s, ...);

static int fsput_s(const char *s);
static int fsput_u(unsigned integer);
static int fsput_u_plus_1(unsigned integer);
static int fsput_d(int integer);

int main(void)
{
min_printf(
"\n%%u 9u is %u.\n%%d 9 is %d.\n"
"%%s \"nine\" is %s.\n%%c '9' is %c.\n",
9u, 9, "nine", '9'
);
return 0;
}

static int fsput_s(const char *s)
{
int count;

for (count = 0; *s != '\0'; ++s) {
if (put_char(*s) == EOF && ferror(stdout) != 0) {
return EOF;
}
++count;
}
return count;
}

static int fsput_d(int integer)
{
int count;

if (0 > integer) {
if (put_char('-') != EOF) {
count = fsput_u_plus_1(-(integer + 1));
if (count != EOF) {
++count;
}
} else {
count = EOF;
}
} else {
count = fsput_u(integer);
}
return count;
}

static int fsput_u(unsigned integer)
{
int count;
unsigned digit, tenth;

tenth = integer / 10;
digit = integer - 10 * tenth + '0';
count = tenth != 0 ? fsput_u(tenth) : 0;
return count != EOF && put_char(digit) != EOF ? count + 1 : EOF;
}

static int fsput_u_plus_1(unsigned integer)
{
int count;
unsigned digit, tenth;

tenth = integer / 10;
digit = integer - 10 * tenth + '0';
if (digit == '9') {
if (tenth != 0) {
count = fsput_u_plus_1(tenth);
} else {
count = put_char('1') == EOF ? EOF : 1;
}
digit = '0';
} else {
count = tenth != 0 ? fsput_u(tenth) : 0;
++digit;
}
return count != EOF && put_char(digit) != EOF ? count + 1 : EOF;
}

int min_printf(const char *s, ...)
{
int count, increment;
va_list ap;

va_start(ap, s);
for (count = 0; *s != '\0'; ++s) {
if (*s == '%') {
switch (*++s) {
case 'c':
increment = fsput_char(va_arg(ap, int));
break;
case 'd':
increment = fsput_d(va_arg(ap, int));
break;
case 's':
increment = fsput_s(va_arg(ap, char *));
break;
case 'u':
increment = fsput_u(va_arg(ap, unsigned));
break;
default:
increment = fsput_char(*s);
break;
}
} else {
increment = fsput_char(*s);
}
if (increment != EOF) {
count += increment;
} else {
count = EOF;
break;
}
}
va_end(ap);
return count;
}

/* END min_printf.c */
--
pete
Nov 14 '05 #8

P: n/a
ch***********@hotmail.com wrote:
put float to double
put char to int
why ?
If you will read my post
<Wn****************@newsread3.news.atl.earthlink.n et> you will see that
I have answered this.
before ask first question i fix the code like you
but i donot think it is right

i think sizeof (char ) != sizeof(int)
sizeof (float) != sizeof(double)


There is no guarantee that either of these is true. They are also not
relevant.
Nov 14 '05 #9

P: n/a

"Martin Ambuhl" <ma*****@earthlink.net>
??????:XA****************@newsread3.news.atl.earth link.net...
ch***********@hotmail.com wrote:
put float to double
put char to int
why ?


If you will read my post
<Wn****************@newsread3.news.atl.earthlink.n et> you will see that
I have answered this.
before ask first question i fix the code like you
but i donot think it is right

i think sizeof (char ) != sizeof(int)
sizeof (float) != sizeof(double)


There is no guarantee that either of these is true. They are also not
relevant.

Nov 14 '05 #10

This discussion thread is closed

Replies have been disabled for this discussion.