program having printf() function invocation without including <stdio.h>

Discussion in 'C Programming' started by sam_cit@yahoo.co.in, Jan 13, 2007.

  1. Guest

    Hi Everyone,

    int main()
    {
    printf("not included stdio.h");
    }

    Yes, i haven't included stdio.h and my compiler would generate a
    warning and would assume that it would return a int, my question is how
    does the linker manage to link the function invocation to the proper
    printf function?
    and does including a header file having function prototype help the
    linker in any way?
     
    , Jan 13, 2007
    #1
    1. Advertising

  2. In article <>,
    <> wrote:
    >Hi Everyone,
    >
    > int main()
    > {
    > printf("not included stdio.h");
    > }
    >
    > Yes, i haven't included stdio.h and my compiler would generate a
    >warning and would assume that it would return a int, my question is how
    >does the linker manage to link the function invocation to the proper
    >printf function?
    > and does including a header file having function prototype help the
    >linker in any way?


    The droids will tell you that this is undefined behavior, for all the
    usual drecky reasons.
     
    Kenny McCormack, Jan 13, 2007
    #2
    1. Advertising

  3. santosh Guest

    wrote:
    > Hi Everyone,
    >
    > int main()
    > {
    > printf("not included stdio.h");
    > }
    >
    > Yes, i haven't included stdio.h and my compiler would generate a
    > warning and would assume that it would return a int, my question is how
    > does the linker manage to link the function invocation to the proper
    > printf function?
    > and does including a header file having function prototype help the
    > linker in any way?


    The prototype is primarily for the compiler's benifit, as it specifies
    the number and type of parameters the function expects, if any, and the
    type of value it returns, if any. It helps the compiler to output the
    correct object code when the function is called and to perform the
    correct conversions on the return value.

    The linker will simply search the library archive files specified for
    the label 'printf'/'_printf' and link in the object code. It doesn't
    need the function's prototype.

    Strictly according to the standard calling a function whose prototype
    is not in scope leads to undefined behaviour. It might work for simpler
    functions on some implementations. Some compilers like gcc, often have
    the ability to "magically" recognise certain common functions and
    include the code inline, but all these are implementation specific
    behaviour. You cannot portably rely on them.
     
    santosh, Jan 13, 2007
    #3
  4. jacob navia Guest

    Re: program having printf() function invocation without including<stdio.h>

    a écrit :
    > Hi Everyone,
    >
    > int main()
    > {
    > printf("not included stdio.h");
    > }
    >
    > Yes, i haven't included stdio.h and my compiler would generate a
    > warning and would assume that it would return a int, my question is how
    > does the linker manage to link the function invocation to the proper
    > printf function?
    > and does including a header file having function prototype help the
    > linker in any way?
    >


    1) Linkers deal with object files, this has nothing to do with header
    files.
    2) Header files describe interfaces of functions and modules. This has
    nothing to do with object files.

    Please keep those apart.

    Now, the interfaces descriptions are for the compiler, that generates
    code according to those descriptions.

    When (in C ) a prototype is not in scope, an automatic
    prototype is provided by the compiler. It assumes a function that
    has an undertemined number of arguments and returns an int.

    In both cases, whether a prototype is in scope or not,
    an external reference to a function is issued by the compiler.
    In this case the object code would contain an external
    reference to the function "printf" (or "_printf", it depends
    on the compiler).

    The linker goes through the object files and sees:
    "Mmmm this is an external reference to the printf function.
    Let's look if I find it somewhere".

    Then, depending on the linker, it will find it or not in the
    libraries it uses BY DEFAULT.

    Default libraries vary from compiler system to compiler system.
    At least the startup code is ALWAYS automatically included,
    then, most compilers assume the C library as a default
    library, i;e. one that you do not need to include in the
    linker command line. Other compilers may differ, for example some
    braindead compiler systems force you to write the math
    library as an extra command line option, and it is not
    included by default, so if you use the sqrt function for
    instance, compilation will fail unless you tell the linker to
    add the math library.

    Others will include a lot of default libraries so that your
    code mostly will link without specifying any extra library
    Microsoft Visual C for instance will include all these:

    comctl32.lib shlwapi.lib kernel32.lib user32.lib gdi32.lib
    winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib
    oleaut32.lib uuid.lib odbc32.lib odbccp32.lib

    Other compiler systems will be less bloated, for instance
    lcc-win32 includes just 6-7 libraries.

    Then, the answer to your question is simple:
    The linker finds the printf function in the C library of
    the compiler that is included by default.

    jacob
     
    jacob navia, Jan 13, 2007
    #4
  5. santosh <> wrote:

    > Strictly according to the standard calling a function whose prototype
    > is not in scope leads to undefined behaviour.


    That's not completely true. Calling a variadic function like printf()
    without its prototype in scope yields UB. I'm not enough of a
    language lawyer to parse 6.5.2.2 for you, but the fact that Annex J.2
    is at pains to note when a function call without a function prototype
    yields UB seems to indicate that there are cases where the behavior is
    not undefined.

    --
    C. Benson Manica | I *should* know what I'm talking about - if I
    cbmanica(at)gmail.com | don't, I need to know. Flames welcome.
     
    Christopher Benson-Manica, Jan 13, 2007
    #5
  6. said:

    > Hi Everyone,
    >
    > int main()
    > {
    > printf("not included stdio.h");
    > }
    >
    > Yes, i haven't included stdio.h


    and so you have called a variadic function without a valid prototype in
    scope, as a result of which the behaviour of the program is undefined.

    May I recommend "The C Programming Language", 2nd edition, by Brian W
    Kernighan and Dennis M Ritchie? Reading it (slowly - its information
    density is extremely high) will answer many of your questions.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
     
    Richard Heathfield, Jan 13, 2007
    #6
  7. Re: program having printf() function invocation without including<stdio.h>

    Christopher Benson-Manica <> writes:
    > santosh <> wrote:
    >
    >> Strictly according to the standard calling a function whose prototype
    >> is not in scope leads to undefined behaviour.

    >
    > That's not completely true. Calling a variadic function like printf()
    > without its prototype in scope yields UB. I'm not enough of a
    > language lawyer to parse 6.5.2.2 for you, but the fact that Annex J.2
    > is at pains to note when a function call without a function prototype
    > yields UB seems to indicate that there are cases where the behavior is
    > not undefined.


    In C99, you can't call a function unless a declaration for it is
    visible, but that declaration needn't be a prototype (i.e., it needn't
    specify the parameter types). It *should*, and there's no good reason
    not to, but non-prototype declarations are allowed for backward
    compatibility.

    For example:

    void foo();

    ...

    foo("hello", 42);

    This is ok if the *definition* of foo() specifies that it returns
    void, has two parameters of types char* and int, and that it's not
    variadic.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jan 13, 2007
    #7
  8. Re: program having printf() function invocation without including<stdio.h>

    In article <>,
    Keith Thompson <> wrote:

    >In C99, you can't call a function unless a declaration for it is
    >visible, but that declaration needn't be a prototype


    In C90 and earlier, if you call a function without a declaration it
    will be assumed to return int, and its arguments will be subject to
    the default promotions, and it will be assumed to be non-variadic
    (variadic functions might have a different calling convention).

    In practice, most compilers by default just warn about undeclared
    functions, and things often work unless the return type is a
    floating-point number or (on systems with ints and pointers of
    different size) a pointer. It's a really bad idea to rely on it
    though, because it may work on one system but not another, so
    take note of compiler warnings!

    -- Richard
    --
    "Consideration shall be given to the need for as many as 32 characters
    in some alphabets" - X3.4, 1963.
     
    Richard Tobin, Jan 14, 2007
    #8
  9. Chris Torek Guest

    In article <>
    <> wrote:
    >... i haven't included stdio.h and my compiler would generate a
    >warning and would assume that it would return a int, my question is how
    >does the linker manage to link the function invocation to the proper
    >printf function?


    Some have described the process by which particular specific linkers
    happen to -- by "designed-in luck", as it were, although whether that
    is "good luck" or "bad luck" is something of a matter of opinion --
    make your call to printf() to a printf() routine in a library.

    At least one person has noted that the behavior is officially
    undefined.

    There are some (rare) implementations on which the linker does
    *not* manage to link your call to a library printf. So asking how
    it did manage presupposes that you do not have such an implementation
    -- it is a little like asking why sheep are white. (White sheep
    are white for various reasons, but black sheep do exist.)

    > and does including a header file having function prototype help the
    >linker in any way?


    It might. It might not. These things depend on the implementation.
    Consider C++ for a moment, and note that C++ compilers commonly
    use a technique called "name mangling", in which source-code function
    names are replaced with link-time "mangled" names that encode the
    *type* of the function as well as the original name. There is no
    reason a C compiler could not do the same thing, so that:

    int foo(void);
    ...
    result = foo();

    causes the linker to search for a name like i$foo$v. Including
    stdio.h, which has to declare "printf" as having type int(const
    char *,...) might tell the compiler to cause the linker to search
    for i$printf$V.pc; but failure to include that header would leave
    the compiler searching for i$printf$pc, so that the link would
    fail.
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
     
    Chris Torek, Jan 15, 2007
    #9
  10. Chris Torek wrote:
    > Consider C++ for a moment, and note that C++ compilers commonly
    > use a technique called "name mangling", in which source-code function
    > names are replaced with link-time "mangled" names that encode the
    > *type* of the function as well as the original name. There is no
    > reason a C compiler could not do the same thing, so that:
    >
    > int foo(void);
    > ...
    > result = foo();
    >
    > causes the linker to search for a name like i$foo$v. Including
    > stdio.h, which has to declare "printf" as having type int(const
    > char *,...) might tell the compiler to cause the linker to search
    > for i$printf$V.pc; but failure to include that header would leave
    > the compiler searching for i$printf$pc, so that the link would
    > fail.


    While name mangling is not prohibited, it is considerably more
    difficult to implement in C, since function prototypes are not
    required. There is nothing preventing a program from doing this:

    a.c:
    int (*get_puts(void))()
    {
    extern int puts();
    return &puts;
    }

    b.c:
    extern int (*get_puts(void))();
    int main(void)
    {
    (*get_puts()) ((const char *) "Hello, world!");
    }

    When a.c is compiled, the compiler cannot know which types of arguments
    puts expects. It may have special knowledge for the standard library
    functions, but I could just as easily have used a user-defined function.
     
    =?utf-8?B?SGFyYWxkIHZhbiBExLNr?=, Jan 15, 2007
    #10
  11. Chris Torek Guest

    >Chris Torek wrote:
    >> ... There is no reason a C compiler could not do [C++-like name mangling]


    In article <>
    Harald van Dijk <> wrote:
    >While name mangling is not prohibited, it is considerably more
    >difficult to implement in C, since function prototypes are not
    >required.


    Yes, I actually considered that but decided to omit details from
    the sketch I posted.

    The trick is that you can declare a function with prototype entirely
    omitted:

    /* optional: include "extern" keyword */ T func();

    or with a full prototype:

    /* extern */ T func(T1 arg1, T2 arg2, T3 arg3);

    but not with any sort of "partial prototype". Moreover, a prototype
    is always required if the function is variadic. Given the syntax I
    suggested -- type-code, $, function-name, $, "V." for variadic, then
    a sequence of type-codes separated by "$" signs, the linker would be
    obligated to match a compiler reference of:

    i$puts

    to an actual:

    i$puts$pc

    symbol. However, i$puts$pi -- int puts(int *) -- would not match
    to i$puts$pc -- int puts(char *). (Note that I also dropped "const"
    in this particular notation. I am not sure off-hand whether it
    would be OK to require const and volatile qualifiers to match.)

    Because prototypes are required for variadic functions, "i$printf"
    would not match "i$printf$V.pc", even though "i$puts" does match
    "i$puts$pc".

    The linker algorithm, in this notation, is more or less:

    /*
    * Test for function call symbol match.
    * Return true if ref (a reference) matches def (a definition).
    * The arguments may be modified temporarily.
    */
    int function_matchp(char *ref, char *def) {
    int ndollar = count_char(ref, '$');

    if (ndollar == 1) {
    /*
    * The reference did not use a prototype, so we match
    * any non-variadic function with the same name and
    * return type.
    */
    char *args;

    args = find_arguments(def); /* roughly, two strchr()s for '$' */
    if (args == NULL)
    panic("function_matchp");
    if (strncmp(args, "V.") == 0) /* def says it's variadic */
    return 0; /* can't match without a prototype */

    /* match against just the type and name */
    if (strncmp(ref, def, args - def) != 0)
    return 0;
    if (warningcontrol.sloppy_match)
    warn("matched non-prototyped call to %F to %F\n", ref, def);
    return 1;
    }

    /*
    * Reference included a prototype, so go for exact match.
    */
    return strcmp(ref, def) == 0;
    }
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
     
    Chris Torek, Jan 15, 2007
    #11
  12. Chris Torek wrote:
    > >Chris Torek wrote:
    > >> ... There is no reason a C compiler could not do [C++-like name mangling]

    >
    > In article <>
    > Harald van Dijk <> wrote:
    > >While name mangling is not prohibited, it is considerably more
    > >difficult to implement in C, since function prototypes are not
    > >required.

    >
    > Yes, I actually considered that but decided to omit details from
    > the sketch I posted.
    >
    > The trick is that you can declare a function with prototype entirely
    > omitted:
    >
    > /* optional: include "extern" keyword */ T func();
    >
    > or with a full prototype:
    >
    > /* extern */ T func(T1 arg1, T2 arg2, T3 arg3);
    >
    > but not with any sort of "partial prototype". Moreover, a prototype
    > is always required if the function is variadic. Given the syntax I
    > suggested -- type-code, $, function-name, $, "V." for variadic, then
    > a sequence of type-codes separated by "$" signs, the linker would be
    > obligated to match a compiler reference of:
    >
    > i$puts
    >
    > to an actual:
    >
    > i$puts$pc
    >
    > symbol. However, i$puts$pi -- int puts(int *) -- would not match
    > to i$puts$pc -- int puts(char *).


    That would be possible.

    > (Note that I also dropped "const"
    > in this particular notation. I am not sure off-hand whether it
    > would be OK to require const and volatile qualifiers to match.)


    The intent is that it is not allowed, and this intent is expressed in
    the footnote attached to 6.2.5p25, but the normative text does not
    state this (hence the cast in my example).

    > Because prototypes are required for variadic functions, "i$printf"
    > would not match "i$printf$V.pc", even though "i$puts" does match
    > "i$puts$pc".
    >
    > The linker algorithm, in this notation, is more or less:


    That's unnecessarily complicated. :) A compiler that sees a definition
    of a function compatible with an unprototyped declaration may choose to
    emit this function under two different names. Using memcpy because of
    the trivial implementation, the compiler would compile

    void *memcpy(void *restrict s1, const void *restrict s2, size_t n)
    {
    return memmove(s1, s2, n);
    }

    into

    ..extern pv$memcpy
    pv$memcpy:
    ..extern pv$memcpy$pv$pv$i
    pv$memcpy$pv$pv$i:
    jmp memmove

    This way, the linker would not need any knowledge of the meaning of the
    dollar signs, and the logic to detect whether a function is compatible
    with an unprototyped declaration must already be present in the
    compiler anyway.
     
    =?utf-8?B?SGFyYWxkIHZhbiBExLNr?=, Jan 16, 2007
    #12
  13. user923005 Guest

    Kenny McCormack wrote:
    > In article <>,
    > <> wrote:
    > >Hi Everyone,
    > >
    > > int main()
    > > {
    > > printf("not included stdio.h");
    > > }
    > >
    > > Yes, i haven't included stdio.h and my compiler would generate a
    > >warning and would assume that it would return a int, my question is how
    > >does the linker manage to link the function invocation to the proper
    > >printf function?
    > > and does including a header file having function prototype help the
    > >linker in any way?

    >
    > The droids will tell you that this is undefined behavior, for all the
    > usual drecky reasons.


    I have literally seen this sort of thing cause program crash. On some
    compilers, the calling convention will tell the compiler how to unpile
    the stack. If you compile with an option to (for instance) change who
    does the pushing and/or popping or to pass the values in registers,
    then the program can crash (or do anything else it wants to).

    If you write crappy code, expect a crappy result. It may not
    necessarily cause demons or Scott Nudds to come flying out of your left
    nostril, but it might fetch a bunch of lawyers from the elevator.
     
    user923005, Jan 16, 2007
    #13
  14. Ben Pfaff Guest

    "user923005" <> writes:

    > Kenny McCormack wrote:
    >> In article <>,
    >> <> wrote:
    >> > int main()
    >> > {
    >> > printf("not included stdio.h");
    >> > }

    >>
    >> The droids will tell you that this is undefined behavior, for all the
    >> usual drecky reasons.

    >
    > I have literally seen this sort of thing cause program crash. On some
    > compilers, the calling convention will tell the compiler how to unpile
    > the stack. [...]


    As far as I know, though, the lack of terminating new-line on the
    program's output really is drecky as a reason for undefined
    behavior, beyond the mundane possibility of the line not
    appearing at all.
    --
    "Am I missing something?"
    --Dan Pop
     
    Ben Pfaff, Jan 16, 2007
    #14
  15. CBFalconer Guest

    Re: program having printf() function invocation without including<stdio.h>

    Ben Pfaff wrote:
    >

    .... snip ...
    >
    > As far as I know, though, the lack of terminating new-line on the
    > program's output really is drecky as a reason for undefined
    > behavior, beyond the mundane possibility of the line not
    > appearing at all.


    Well, isn't that undefined behaviour. What if that final line was:

    "Internal error - ignore previous results".

    in a medical treatment recommendation system.

    --
    "A man who is right every time is not likely to do very much."
    -- Francis Crick, co-discover of DNA
    "There is nothing more amazing than stupidity in action."
    -- Thomas Matthews
    <http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
     
    CBFalconer, Jan 16, 2007
    #15
  16. Ben Pfaff said:

    > "user923005" <> writes:
    >
    >> Kenny McCormack wrote:
    >>> In article <>,
    >>> <> wrote:
    >>> > int main()
    >>> > {
    >>> > printf("not included stdio.h");
    >>> > }
    >>>
    >>> The droids will tell you that this is undefined behavior, for all the
    >>> usual drecky reasons.

    >>
    >> I have literally seen this sort of thing cause program crash. On some
    >> compilers, the calling convention will tell the compiler how to unpile
    >> the stack. [...]

    >
    > As far as I know, though, the lack of terminating new-line on the
    > program's output really is drecky as a reason for undefined
    > behavior, beyond the mundane possibility of the line not
    > appearing at all.


    Um, the reason for the undefined behaviour was the omission of a prototype
    for a variadic function.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
     
    Richard Heathfield, Jan 16, 2007
    #16
  17. Ben Pfaff Guest

    Richard Heathfield <> writes:

    > Ben Pfaff said:
    >
    >> "user923005" <> writes:
    >>
    >>> Kenny McCormack wrote:
    >>>> In article <>,
    >>>> <> wrote:
    >>>> > int main()
    >>>> > {
    >>>> > printf("not included stdio.h");
    >>>> > }
    >>>>
    >>>> The droids will tell you that this is undefined behavior, for all the
    >>>> usual drecky reasons.
    >>>
    >>> I have literally seen this sort of thing cause program crash. On some
    >>> compilers, the calling convention will tell the compiler how to unpile
    >>> the stack. [...]

    >>
    >> As far as I know, though, the lack of terminating new-line on the
    >> program's output really is drecky as a reason for undefined
    >> behavior, beyond the mundane possibility of the line not
    >> appearing at all.

    >
    > Um, the reason for the undefined behaviour was the omission of a prototype
    > for a variadic function.


    That's another reason, and the most obvious one, but C89 and C99
    both clearly state that, for text streams:

    Whether the last line requires a terminating new-line
    character is implementation-defined.
    --
    Just another C hacker.
     
    Ben Pfaff, Jan 16, 2007
    #17
  18. Ben Pfaff Guest

    Re: program having printf() function invocation without including <stdio.h>

    CBFalconer <> writes:

    > Ben Pfaff wrote:
    >>

    > ... snip ...
    >>
    >> As far as I know, though, the lack of terminating new-line on the
    >> program's output really is drecky as a reason for undefined
    >> behavior, beyond the mundane possibility of the line not
    >> appearing at all.

    >
    > Well, isn't that undefined behaviour. What if that final line was:
    >
    > "Internal error - ignore previous results".
    >
    > in a medical treatment recommendation system.


    Yes, it's undefined behavior. The "drecky" part is that the C
    standard doesn't constrain behavior more tightly. It would be
    perfectly reasonable in my opinion if it said something like "If
    a text stream does not end in a new-line, the implementation may
    drop the line or add a new-line itself" instead of making it so
    wide-ranging.
    --
    "We put [the best] Assembler programmers in a little glass case in the hallway
    near the Exit sign. The sign on the case says, `In case of optimization
    problem, break glass.' Meanwhile, the problem solvers are busy doing their
    work in languages most appropriate to the job at hand." --Richard Riehle
     
    Ben Pfaff, Jan 16, 2007
    #18
  19. In article <>,
    Richard Heathfield <> wrote:
    ....
    >Um, the reason for the undefined behaviour was the omission of a prototype
    >for a variadic function.


    Correct. The other is just in the category of "You may not see the
    output", not in the "UB" category.
     
    Kenny McCormack, Jan 17, 2007
    #19
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Joona I Palaste

    Re: Output without stdio.h or iostream

    Joona I Palaste, Jul 3, 2003, in forum: C Programming
    Replies:
    0
    Views:
    727
    Joona I Palaste
    Jul 3, 2003
  2. Lew Pitcher

    Re: Output without stdio.h or iostream

    Lew Pitcher, Jul 3, 2003, in forum: C Programming
    Replies:
    0
    Views:
    758
    Lew Pitcher
    Jul 3, 2003
  3. Jeremy L. Moles

    Having to "print" before method invocation?

    Jeremy L. Moles, Mar 8, 2006, in forum: Python
    Replies:
    0
    Views:
    251
    Jeremy L. Moles
    Mar 8, 2006
  4. Replies:
    18
    Views:
    1,936
    crazzybugger
    Oct 22, 2006
  5. ben
    Replies:
    4
    Views:
    664
    Martin Ambuhl
    Jun 26, 2004
Loading...

Share This Page