Unknown function

Discussion in 'C Programming' started by Christian Christmann, Mar 5, 2006.

  1. Hi,

    I was just going through this exercise
    http://www.cas.mcmaster.ca/~franek/books/membook-answers/ch4/answers-ch4-3.html
    and I'am confused about the answer.

    It says: "... the compiler actually does not "know" the signature of
    malloc(), hence it assumes by default, that it returns int..."

    How can the function call of 'malloc' work at all if it is unknown?
    I thought that each function that is unknown to the compiler at a specific
    point of the program leads to an 'undefined reference' when tried
    to get linked.

    Can you shed some light onto it.

    Thank you.

    Chris
    Christian Christmann, Mar 5, 2006
    #1
    1. Advertising

  2. Christian Christmann

    Michael Mair Guest

    Christian Christmann schrieb:
    > Hi,
    >
    > I was just going through this exercise
    > http://www.cas.mcmaster.ca/~franek/books/membook-answers/ch4/answers-ch4-3.html
    > and I'am confused about the answer.
    >
    > It says: "... the compiler actually does not "know" the signature of
    > malloc(), hence it assumes by default, that it returns int..."
    >
    > How can the function call of 'malloc' work at all if it is unknown?
    > I thought that each function that is unknown to the compiler at a specific
    > point of the program leads to an 'undefined reference' when tried
    > to get linked.
    >
    > Can you shed some light onto it.


    The author of this page does either not tell the whole truth (assuming
    a certain kind of implementations) or does not know better (if
    considered from the standard C point of view).

    Without prototype in scope, malloc() indeed is assumed to return int.

    The conversion from int to void * or backwards is allowed;
    however, it is not guaranteed to be without loss. As char * and void *
    essentially have the same size, representation and alignment, we can
    treat them the same at the moment.
    _If_ it is without loss, i.e. if for all possible integer and pointer
    values
    p = i; i = p;
    and
    i = p; p = i;
    yield the original i and p, respectively, and sizeof i == sizeof p
    then chances are good that everything works automagically.
    If the return conventions of pointers and integers are different or
    sizeof void * > sizeof i or the conversion is not lossless, then it
    may very well go wrong, maybe always, maybe sometimes.

    This is not the whole truth either; does this already answer your
    question?

    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
    Michael Mair, Mar 5, 2006
    #2
    1. Advertising

  3. Christian Christmann wrote:
    > It says: "... the compiler actually does not "know" the signature of
    > malloc(), hence it assumes by default, that it returns int..."
    >
    > How can the function call of 'malloc' work at all if it is unknown?
    > I thought that each function that is unknown to the compiler at a specific
    > point of the program leads to an 'undefined reference' when tried
    > to get linked.


    No (at least not in C89)

    If there is no definition or prototype the compiler assumes (because
    the standard tells it to) that malloc() takes int arguments and
    returns an int. As you clearly understand, this is going to be a
    problem since malloc actually takes size_t and returns void *. Since
    20 is a valid value to pass to a function that takes either int or
    size_t, the compiler doesn't know that the argument is wrong, but it
    does know that the return value is wrong, hence the warning.

    It is not unusual for the code to work on a particular implementation,
    since size_t is often a typedef for int, and pointers may be
    implemented as integers of the same size as int. When it doesn't work,
    it can just as easily be because the argument type is wrong as because
    the return type is wrong. For example, on 64-bit hardware, void * and
    size_t may both be 64-bit types and int a 32-bit type. The reason the
    compiler complains [and is required to complain] about the return value
    but not the argument is that the return value problem is easily
    detectable.

    The warning is misleading, since it suggests that adding a cast would
    solve the problem. This is not true in general and is very unlikely to
    be true in practice. Writing
    p = (char *) malloc(20);
    is likely to make the warning go away, but if void * return values are
    passed differently than ints
    or are a different size then the cast is not going to magically
    retrieve the lost information. This code doesn't say "malloc returns a
    char *", it says "although malloc returns an int, I want the compiler
    to pretend that it is a char *". For this to be helpful you need a
    strange implementation where void * and int are stored and returned
    from functions in the same way but char * is stored differently.

    A more helpful compiler message might mention that the return value of
    int came from the "implicit int" rule rather than an actual
    declaration. Something like: "use of undeclared function malloc() does
    not match implicit declaration". However, it could be worse. The
    Standard permits the compiler to give even less helpful messages such
    as "There might be a problem with line 42".


    -thomas
    Thomas Lumley, Mar 5, 2006
    #3
  4. Christian Christmann

    Jordan Abel Guest

    On 2006-03-05, Christian Christmann <> wrote:
    > Hi,
    >
    > I was just going through this exercise
    > http://www.cas.mcmaster.ca/~franek/books/membook-answers/ch4/answers-ch4-3.html
    > and I'am confused about the answer.
    >
    > It says: "... the compiler actually does not "know" the signature of
    > malloc(), hence it assumes by default, that it returns int..."
    >
    > How can the function call of 'malloc' work at all if it is unknown?
    > I thought that each function that is unknown to the compiler at a specific
    > point of the program leads to an 'undefined reference' when tried
    > to get linked.


    It doesn't know the signature of malloc at phase 7, but it knows of the
    existence of a function called 'malloc' at phase 8.
    Jordan Abel, Mar 5, 2006
    #4
  5. "Thomas Lumley" <> writes:
    [...]
    > It is not unusual for the code to work on a particular implementation,
    > since size_t is often a typedef for int, and pointers may be
    > implemented as integers of the same size as int.


    Slight quibble: size_t can be a typedef for unsigned int.

    --
    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, Mar 6, 2006
    #5
  6. > Without prototype in scope, malloc() indeed is assumed to return int.
    >


    Actually this is my question.
    An easy example:

    int main()
    {
    func();
    return 0;
    }

    void func()
    {
    int a = 10;
    }

    Of course, the compiler complains that it does not know the function
    'func' in the 'mai' function since it's unknown to it at that
    point of the compilation process.
    So, when the author mentions on his website (I mentioned in my first
    message) "the compiler actually dos not "know" the signature of
    malloc()", I understand it in the way that malloc is not known to the
    compiler at that specific point of program.

    Or is it possible for a function to be known to the compiler without
    a prototype? If so, could you give me a short example.


    The casting you described in your previous message is clear now. Thank
    you.

    Thank you.
    Chris
    Christian Christmann, Mar 7, 2006
    #6
  7. Christian Christmann

    Flash Gordon Guest

    Christian Christmann wrote:

    Please leave in attribution lines, the bits that say who said what. It
    makes it easier to follow the thread.

    >> Without prototype in scope, malloc() indeed is assumed to return int.

    >
    > Actually this is my question.
    > An easy example:
    >
    > int main()
    > {
    > func();
    > return 0;
    > }
    >
    > void func()
    > {
    > int a = 10;
    > }
    >
    > Of course, the compiler complains that it does not know the function
    > 'func' in the 'mai' function since it's unknown to it at that
    > point of the compilation process.
    > So, when the author mentions on his website (I mentioned in my first
    > message) "the compiler actually dos not "know" the signature of
    > malloc()", I understand it in the way that malloc is not known to the
    > compiler at that specific point of program.
    >
    > Or is it possible for a function to be known to the compiler without
    > a prototype? If so, could you give me a short example.


    There are a couple of different issues here. What the standard mandates
    that the compiler must do and what the compiler can do in addition to
    what the standard mandates. Also, what the standard mandates is
    different in the most commonly implemented version of the standard (C90)
    to the current version of the standard (C99). In the following I'm
    assuming C90 (the commonly implemented standard). I'm also not going to
    go in to the details of all the steps of the compilation.

    The compiler first processes all the pre-processor directives, such as
    #include. This in effect produces one very long source file with
    everything in it which is then passed to the actual C compiler. If a
    call to a function occurs in the pre-processed C file before a
    definition is encounters the C standard mandates that the compiler treat
    it as a function returning an int and taking an unspecified number of
    parameters.

    Now on to bits compilers are allowed to do but the standard does not
    mandate. The standard mandates that under some conditions the compiler
    produce a diagnostic (typically reported as a warning or error), such as
    reporting a syntax error. However, the standard also allows the compiler
    to produce diagnostics for any other reason it chooses. So, although the
    compiler is required to assume malloc returns an int if it has not yet
    seen a declaration of it, it is also allowed to say, "ah, but I know
    malloc actually returns a void* because that is what the standard malloc
    function returns, so I'm going to be nice and tell the user that they
    have got it wrong." Indeed, some compilers will actually do this even
    though it is not required. So in that sense a compiler writer can choose
    to make the compiler "know" more than the standard says it has to know
    and produce more helpful messages as a result.

    So, given the following example of a *bad* program:

    int main(void)
    {
    int i = malloc(5);
    return 0;
    }

    The compiler is not *required* to produce an diagnostics (errors or
    warnings), since it is required to assume that malloc returns an int
    because it has not seen a diagnostic. However, some compilers will tell
    you that this disagrees which what it knows is the standard declaration
    of malloc.

    A more common example of the same problem is:
    int main(void)
    {
    int *ptr = (int*)malloc(5);
    return 0;
    }

    Again, the compiler is required to assume that malloc returns an int,
    which we all know is wrong. The cast then tells the compiler to convert
    that expected in in to a pointer. So again, the compiler is *not*
    required to complain. However, as before, there are some compilers that
    will be helpful and complain.

    As a final example, given:
    int main(void)
    {
    int *ptr = malloc(5);
    return 0;
    }
    The compiler is required to assume that malloc returns an int. However,
    the standard also requires a diagnostic on attempting to assign an int
    directly to a pointer. So due to the lack of the cast and the required
    assumed return type of malloc, the compiler is *required* to produce a
    diagnostic. Often the diagnostic will be something like, "attempt to
    assign integer to pointer without cast" which often leads people who
    don't know any better to add in the cast changing it to the previous
    example.

    Since malloc does not return an int, not of the examples I've given are
    required to "work" whether or not the compiler complains and there are
    real modern systems (some modern 64 bit systems in certain common modes)
    where it will *not* work.
    --
    Flash Gordon, living in interesting times.
    Web site - http://home.flash-gordon.me.uk/
    comp.lang.c posting guidelines and intro:
    http://clc-wiki.net/wiki/Intro_to_clc
    Flash Gordon, Mar 7, 2006
    #7
  8. Christian Christmann

    CBFalconer Guest

    Flash Gordon wrote:
    >

    .... snip ...
    >
    > There are a couple of different issues here. What the standard
    > mandates that the compiler must do and what the compiler can do
    > in addition to what the standard mandates. Also, what the
    > standard mandates is different in the most commonly implemented
    > version of the standard (C90) to the current version of the
    > standard (C99). In the following I'm assuming C90 (the commonly
    > implemented standard). I'm also not going to go in to the
    > details of all the steps of the compilation.
    >
    > The compiler first processes all the pre-processor directives,
    > such as #include. This in effect produces one very long source
    > file with everything in it which is then passed to the actual C
    > compiler. If a call to a function occurs in the pre-processed C
    > file before a definition is encounters the C standard mandates
    > that the compiler treat it as a function returning an int and
    > taking an unspecified number of parameters.


    Correction. This first encountered call effectively defines the
    number and type of parameters for the function. Now all other
    calls should agree, but will not be checked for agreement, leading
    to optimum conditions for black fly breeding.

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
    More details at: <http://cfaj.freeshell.org/google/>
    Also see <http://www.safalra.com/special/googlegroupsreply/>
    CBFalconer, Mar 8, 2006
    #8
  9. On Sun, 05 Mar 2006 22:58:33 +0100, Michael Mair
    <> wrote:

    >Christian Christmann schrieb:
    >> Hi,
    >>
    >> I was just going through this exercise
    >> http://www.cas.mcmaster.ca/~franek/books/membook-answers/ch4/answers-ch4-3.html
    >> and I'am confused about the answer.
    >>
    >> It says: "... the compiler actually does not "know" the signature of
    >> malloc(), hence it assumes by default, that it returns int..."
    >>
    >> How can the function call of 'malloc' work at all if it is unknown?
    >> I thought that each function that is unknown to the compiler at a specific
    >> point of the program leads to an 'undefined reference' when tried
    >> to get linked.
    >>
    >> Can you shed some light onto it.

    >
    >The author of this page does either not tell the whole truth (assuming
    >a certain kind of implementations) or does not know better (if
    >considered from the standard C point of view).
    >
    >Without prototype in scope, malloc() indeed is assumed to return int.


    This is only true in the old standard. The current standard no longer
    supports this assumption.

    >
    >The conversion from int to void * or backwards is allowed;
    >however, it is not guaranteed to be without loss. As char * and void *


    While this is reasonably true, it is irrelevant. Allowing the
    compiler to believe the function returns a different type than it
    actually does leads to undefined behavior. Think about systems where
    a pointer is returned in one type of register and an int in another or
    where pointers and ints have different endian-ness.


    Remove del for email
    Barry Schwarz, Mar 12, 2006
    #9
  10. Barry Schwarz <> writes:
    > On Sun, 05 Mar 2006 22:58:33 +0100, Michael Mair
    > <> wrote:

    [...]
    >>Without prototype in scope, malloc() indeed is assumed to return int.

    >
    > This is only true in the old standard. The current standard no longer
    > supports this assumption.


    But even a C99 compiler is free to do so, as long as it issues a
    diagnostic. It's likely to allow it for backwards compatibility.

    >>The conversion from int to void * or backwards is allowed;
    >>however, it is not guaranteed to be without loss. As char * and void *

    >
    > While this is reasonably true, it is irrelevant. Allowing the
    > compiler to believe the function returns a different type than it
    > actually does leads to undefined behavior. Think about systems where
    > a pointer is returned in one type of register and an int in another or
    > where pointers and ints have different endian-ness.


    Right. A conversion can occur only when the compiler knows the type
    of the expression and the type to which it's converted. If you call
    malloc() with no visible prototype, the compiler doesn't have enough
    information to perform a conversion. At best, it treats the bits of
    the void* result *as if* they were an int representation (whereas a
    conversion might involve a change of representation); at worst,
    arbitrarily bad things can happen.

    --
    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, Mar 12, 2006
    #10
    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. Kapt. Boogschutter
    Replies:
    7
    Views:
    461
    Kapt. Boogschutter
    Jun 20, 2004
  2. Calum

    Calling a function of unknown type

    Calum, Jan 16, 2004, in forum: C Programming
    Replies:
    4
    Views:
    513
    Calum
    Jan 19, 2004
  3. ais523
    Replies:
    6
    Views:
    304
    Richard G. Riley
    Apr 16, 2006
  4. pozz
    Replies:
    8
    Views:
    325
    Jack Klein
    Jul 20, 2006
  5. Vincent Arnoux
    Replies:
    1
    Views:
    230
    Arnaud Bergeron
    Aug 11, 2006
Loading...

Share This Page