is this declaration correct

B

barry

Rather than
include <stdio.h> can I use int printf(const char *,...) correct at all
places if I only use printf in my program..
"You are not going to get it right first time" -> Bjarne Stroustrup
 
K

Keith Thompson

barry said:
Rather than
include <stdio.h> can I use int printf(const char *,...) correct at all
places if I only use printf in my program..

Yes and no.

Yes, in C90 that's the correct declaration.

In C99, the declaration of printf is
int printf(const char * restrict format, ...);
I'm not sure what the standard says about defining a function with
"restrict" and declaring it without "restrict".

But why would you want to do this? I can't think of any good reason not
to just use

#include <stdio.h>
 
P

Peter Nilsson

Keith Thompson said:
....
In C99, the declaration of printf is
    int printf(const char * restrict format, ...);
I'm not sure what the standard says about defining a function with
"restrict" and declaring it without "restrict".

N1256: 6.7.5.3p15: "... (In the determination of type
compatibility ... each parameter declared with qualified type
is taken as having the unqualified version of its declared
type.)"

So, yes, it's fine in C99.
But why would you want to do this?

 I can't think of any good reason not to just use

    #include <stdio.h>

Perhaps:

1) to shorten compile time.
2) declaring printf at block scope localises the
declaration.
3) a freestanding implementation may not supply a stdio.h,
it may be possible to link one in.
 
S

sandeep

Keith said:
Yes and no.

Yes, in C90 that's the correct declaration.

In C99, the declaration of printf is
int printf(const char * restrict format, ...);
I'm not sure what the standard says about defining a function with
"restrict" and declaring it without "restrict".

Also printf may be a macro not a function, for example if I was
implementing a compiler then I would implement fprintf then have
#define printf(s,...) (fprintf(stdout,(s),__VA_ARGS__))
in <stdio.h>.

In this situation linking will fail if you provide your own declaration
of printf!!
 
R

Ralf Damaschke

sandeep said:
Also printf may be a macro not a function, for example if I was
implementing a compiler then I would implement fprintf then have
#define printf(s,...) (fprintf(stdout,(s),__VA_ARGS__))
in <stdio.h>.

In this situation linking will fail if you provide your own declaration
of printf!!

In that case your implementation would not be a conforming one.
It even must allow a
#undef printf
and still accept calls to printf().

-- Ralf
 
E

Eric Sosman

N1256: 6.7.5.3p15: "... (In the determination of type
compatibility ... each parameter declared with qualified type
is taken as having the unqualified version of its declared
type.)"

So, yes, it's fine in C99.


Perhaps:

1) to shorten compile time.

IMHO it would take a very large number of compilations to
recoup the time already spent posting the question and reading
answers.
2) declaring printf at block scope localises the
declaration.

Yes, but why? This would only be advantageous if you also
wanted to use `printf' as an identifier for something else entirely,
like `static double printf[42][36];' or something -- and that's just
plain stupid.
3) a freestanding implementation may not supply a stdio.h,
it may be possible to link one in.

True -- But in that case, we don't know whether the offered
declaration is correct or not, since we don't know what the
free-standing system's `printf' does.
 
K

Keith Thompson

Peter Nilsson said:
Perhaps:

1) to shorten compile time.

If you're compiling a very large number of files on a slow system, the
speedup might even be noticeable -- but I doubt that it would exceed the
extra time spent maintaining the code.
2) declaring printf at block scope localises the
declaration.

How is that useful?
3) a freestanding implementation may not supply a stdio.h,
it may be possible to link one in.

Ok, that's possible (though an implementation that provides printf
but doesn't declare it in a header is not exactly friendly).
 
P

pettybetty66

Also printf may be a macro not a function, for example if I was
implementing a compiler then I would implement fprintf then have
#define printf(s,...) (fprintf(stdout,(s),__VA_ARGS__))
in <stdio.h>.

That's not a valid macro implementation of printf. Consider
printf("Hello world\n");
 
S

sandeep

Ralf said:
In that case your implementation would not be a conforming one. It even
must allow a
#undef printf
and still accept calls to printf().

-- Ralf

I think standard library functions can be implemented as macros, for
example in gcc putc is a macro.
 
E

Eric Sosman

I think standard library functions can be implemented as macros, for
example in gcc putc is a macro.

Yes, but no Standard library function can be implemented
*only* as a macro.

Are you the same Sandeep who's writing his Master's thesis on
the C Standard library? I guess not, because someone undertaking
such an effort would surely have read the Standard's description
of that library, and would have come across 7.1.4p1. Read it, and
you'll then know something the other Sandeep has already learned.
 
S

sandeep

Eric said:
Yes, but no Standard library function can be implemented
*only* as a macro.

In this case gcc is nonconforming...

$ nm /usr/lib/libc.a 2>&1 | grep putc
putchar.o:
0000000000000000 T putchar
putchar_u.o:
0000000000000000 T putchar_unlocked
fputc.o:
0000000000000000 T fputc
putc.o:
0000000000000000 T _IO_putc
0000000000000000 W putc
fputc_u.o:
0000000000000000 T fputc_unlocked
putc_u.o:
0000000000000000 T putc_unlocked
00000000000000f0 T __argp_fmtstream_putc

You see that putc is ONLY provided as a macro!
Are you the same Sandeep who's writing his Master's thesis on
the C Standard library? I guess not, because someone undertaking such
an effort would surely have read the Standard's description of that
library, and would have come across 7.1.4p1. Read it, and you'll then
know something the other Sandeep has already learned.

Of course I can't memorize every detail, however I will browse the
Standard and get the main points and look at any sections on topics of my
specialization.
 
B

Ben Bacarisse

sandeep said:
In this case gcc is nonconforming...

$ nm /usr/lib/libc.a 2>&1 | grep putc
putchar.o:
0000000000000000 T putchar
putchar_u.o:
0000000000000000 T putchar_unlocked
fputc.o:
0000000000000000 T fputc
putc.o:
0000000000000000 T _IO_putc
0000000000000000 W putc
fputc_u.o:
0000000000000000 T fputc_unlocked
putc_u.o:
0000000000000000 T putc_unlocked
00000000000000f0 T __argp_fmtstream_putc

You see that putc is ONLY provided as a macro!

How you conclude that? Did you try this, for example:

#include <stdio.h>

int main(void)
{
(putc)('x', stdout);
(putc)('\n', stdout);
return 0;
}

<snip>
 
I

Ian Collins

How you conclude that? Did you try this, for example:

#include<stdio.h>

int main(void)
{
(putc)('x', stdout);
(putc)('\n', stdout);
return 0;
}

Or

#include <stdio.h>

typedef int (*fn)(int, FILE*);

int main(void)
{
fn f = &putc;
}
 
E

Eric Sosman

Or

#include <stdio.h>

typedef int (*fn)(int, FILE*);

int main(void)
{
fn f = &putc;
}

Or

#include <stdio.h>
#undef putc
int main(void) {
putc('!', stdout);
putc('\n', stdout);
return 0;
}
 
D

David Thompson

Note that this wording is a bit subtle. The things specified in clause
7 as functions *may* *also* be implemented as macros. A few things
*specified* as macros with arguments, aka function-like macros, do not
need to be functions: assert setjmp fpclassify/isless/etc va_start*
va_arg* offsetof* INT[bits|MAX]_C* (the * ones obviously can't be
functions because they take nonvalues and/or return varying types.)
In this case gcc is nonconforming...
(Technically this isn't gcc; it's the library used with gcc, perhaps
glibc, which together make up a C implementation.)
$ nm /usr/lib/libc.a 2>&1 | grep putc
putchar.o:
0000000000000000 T putchar
putchar_u.o:
0000000000000000 T putchar_unlocked
fputc.o:
0000000000000000 T fputc
putc.o:
0000000000000000 T _IO_putc
0000000000000000 W putc
fputc_u.o:
0000000000000000 T fputc_unlocked
putc_u.o:
0000000000000000 T putc_unlocked
00000000000000f0 T __argp_fmtstream_putc

You see that putc is ONLY provided as a macro!
Look again. The 'W' in putc.o *is* a global definition. Merely a
'weak' one that can be overridden by another (user) definition.

That's okay; a conforming implementation (of the library) must have
actual library routines that standard C code *can* reference; if
nonstandard C code defines its own e.g. putc that is UB: the
implementation *may* (detect and) report the error; it *may* just
malfunction; it *may* (and this one does) let the user win; it *may*
create nasal demons, though that's rather hard to implement.
 

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,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top