Help wanted on some source codes

Discussion in 'C Programming' started by Becker, Nov 30, 2005.

  1. Becker

    Becker Guest

    1.===========================================
    /* a.c */
    int x;
    int y;

    void main()
    {
    f();
    printf("%x %x\n", x, y);
    }

    /* b.c */
    double x;

    void f()
    {
    x = -0.0;
    }


    2.===========================================
    /* a.c */
    int x = 1;
    int y;

    void main()
    {
    f();
    printf("%x %x\n", x, y);
    }

    /* b.c */
    double x;

    void f()
    {
    x = -0.0;
    }

    3.===========================================
    /* a.c */
    int x;
    int y = 1;

    void main()
    {
    f();
    printf("%x %x\n", x, y);
    }

    /* b.c */
    double x;

    void f()
    {
    x = -0.0;
    }

    4.===========================================
    /* a.c */
    int x = 1;
    int y = 1;

    void main()
    {
    f();
    printf("%x %x\n", x, y);
    }

    /* b.c */
    double x;

    void f()
    {
    x = -0.0;
    }

    5.===========================================
    /* a.c */
    int x = 1;
    int y = 1;

    void main()
    {
    f();
    printf("%x %x\n", x, y);
    }

    /* b.c */
    double x;

    void f()
    {
    x = -0;
    }


    Remark=======================================
    The above programs from 1 to 5 are all constituted
    of two separate files, a.c & b.c, and can be
    compiled under gcc.
    e.g.
    /* Linux */
    $ gcc -o test a.c b.c
    $ ./test
    /* Windows */
    C:\gcc -o test.exe a.c b.c
    C:\test


    Question=======================================
    I'm wondering about the strange results generated
    by the programs. Please help me. I want to understand
    why the results are like that.
    By the way, the source codes above are in old K&R style
    and will be warned by the gcc, you can change them to
    new ISO/ANSI style :)

    Thanks in advance & best regards!

    Becker
    30-Nov-2005
     
    Becker, Nov 30, 2005
    #1
    1. Advertising

  2. In article <>,
    Becker <> wrote:
    >1.===========================================
    >/* a.c */
    >int x;
    >int y;
    >
    >void main()
    >{
    > f();
    > printf("%x %x\n", x, y);
    >}


    %x expects an unsigned int, not an int.

    >/* b.c */
    >double x;
    >
    >void f()
    >{
    > x = -0.0;
    >}


    You never initialize y at all, and you initialize x to the wrong
    type. double might or might not be the same size as int; it is not
    uncommon for it to be longer, but that is not certain. If it is longer
    then you -might- end up overwritting y, but the relative order of x and
    y are not fixed by the standard, and double might be larger than two
    ints together so you might be scribbling on a random portion of memory.

    If you happen to be using IEEE754 floating point, then -0.0 is
    considered to be different than 0.0 . Even on systems that it is not,
    the floating point representation of 0 is not certain to be all binary
    0's (though -some- floating point standards require that all-binary 0's
    must be treated as floating point 0.)

    Your programs 2 thru 4 are just variations on exactly the same themes
    with various different values initializing the memory that might or might
    not be scribbled over.


    >5.===========================================


    >void f()
    >{
    > x = -0;
    >}


    -0 is an integer constant, and it is the same as 0 on all but the
    rather-uncommon signed-magnitude machines (which are allowed for by
    the standard.) -0 as an integer is thus the same as 0 as an integer.
    That integer is then cast to the double that you have declared x to
    be in this file. On some systems that is different than the floating
    point -0.0 .
    --
    "It is important to remember that when it comes to law, computers
    never make copies, only human beings make copies. Computers are given
    commands, not permission. Only people can be given permission."
    -- Brad Templeton
     
    Walter Roberson, Nov 30, 2005
    #2
    1. Advertising

  3. Becker

    Old Wolf Guest

    Becker wrote:

    > 1.===========================================
    > /* a.c */
    > int x;
    > int y;
    >
    > void main()
    > {
    > f();
    > printf("%x %x\n", x, y);
    > }
    >
    > /* b.c */
    > double x;
    >
    > void f()
    > {
    > x = -0.0;
    > }


    All of your programs have undefined behaviour because there
    are two variables called 'x' with external linkage.

    Also, "%x" is only to be used for unsigned ints, and
    main should return an int (allowing "void main" is compiler-
    specific).

    For an understanding of why GCC gives the results you see,
    please ask your question on a GCC newsgroup.
     
    Old Wolf, Nov 30, 2005
    #3
  4. Becker

    Guest

    Old Wolf wrote:
    > Becker wrote:
    >
    > > 1.===========================================
    > > /* a.c */
    > > int x;
    > > int y;
    > >
    > > void main()
    > > {
    > > f();
    > > printf("%x %x\n", x, y);
    > > }
    > >
    > > /* b.c */
    > > double x;
    > >
    > > void f()
    > > {
    > > x = -0.0;
    > > }

    >
    > All of your programs have undefined behaviour because there
    > are two variables called 'x' with external linkage.
    >


    The programs are rubbish of course. But wouldn't the file scope of x
    mean that function f() is actually refering to the double x instead of
    the int x?
     
    , Nov 30, 2005
    #4
  5. Becker

    Jack Klein Guest

    On 29 Nov 2005 16:45:47 -0800, "Becker" <> wrote in
    comp.lang.c:

    > 1.===========================================
    > /* a.c */
    > int x;
    > int y;
    >
    > void main()
    > {
    > f();
    > printf("%x %x\n", x, y);
    > }
    >
    > /* b.c */
    > double x;
    >
    > void f()
    > {
    > x = -0.0;
    > }


    [snip several other examples]

    Each of your examples defines main() with a return type of void, and
    also has main() call a function without a declaration in scope. There
    is no version of the C standard where a program performing both of
    these actions is legal.

    If you are using gcc as a standard compiler conforming to the C
    standard prior to 1999, 'void main()' invokes undefined behavior
    immediately. Friends don't let friends void main(). If you are using
    gcc as a standard compiler conforming to a 1999 or later version of
    the C standard, it is a constraint violation to call a function
    without a declaration in scope.

    So you are not invoking gcc to conform to any version of the C
    standard, which is just as well, because your program is not actually
    valid C.

    But as to the question you asked, even if you fixed these things:

    Each of your examples defines 'x' with external linkage in two
    different source files. It doesn't even make any difference whether
    'x' has the same type or different types in the two definitions, you
    have broken a rule and have undefined behavior.

    Once you have undefined behavior, it's "game over, thanks for playing,
    Carol will give you some lovely parting gifts". The C language
    neither knows or cares what happens next, there is no right or wrong.
    It could cause the CD drive tray to jump out and hit you in the nose.
    Even if the computer does not have a CD drive.

    The C standard says this in "6.9 External definitions" paragraph 5:

    "An external definition is an external declaration that is also a
    definition of a function (other than an inline definition) or an
    object. If an identifier declared with external linkage is used in an
    expression (other than as part of the operand of a sizeof operator
    whose result is an integer constant), somewhere in the entire program
    there shall be exactly one external definition for the identifier;
    otherwise, there shall be no more than one."

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
     
    Jack Klein, Nov 30, 2005
    #5
  6. Becker

    Jack Klein Guest

    On 29 Nov 2005 18:34:15 -0800, ""
    <> wrote in comp.lang.c:

    > Old Wolf wrote:
    > > Becker wrote:
    > >
    > > > 1.===========================================
    > > > /* a.c */
    > > > int x;
    > > > int y;
    > > >
    > > > void main()
    > > > {
    > > > f();
    > > > printf("%x %x\n", x, y);
    > > > }
    > > >
    > > > /* b.c */
    > > > double x;
    > > >
    > > > void f()
    > > > {
    > > > x = -0.0;
    > > > }

    > >
    > > All of your programs have undefined behaviour because there
    > > are two variables called 'x' with external linkage.
    > >

    >
    > The programs are rubbish of course. But wouldn't the file scope of x
    > mean that function f() is actually refering to the double x instead of
    > the int x?


    This is part of what I posted in a reply to the OP, but I'll repeat it
    here for your benefit. The issue here is NOT file scope, but most
    specifically IS external linkage:

    The C standard says this in "6.9 External definitions" paragraph 5:

    "An external definition is an external declaration that is also a
    definition of a function (other than an inline definition) or an
    object. If an identifier declared with external linkage is used in an
    expression (other than as part of the operand of a sizeof operator
    whose result is an integer constant), somewhere in the entire program
    there shall be exactly one external definition for the identifier;
    otherwise, there shall be no more than one."

    Violating a 'shall' outside of a constraint section is just plain old
    ordinary undefined behavior. You have left planet C behind and
    entered the Twilight Zone, and there is no right or wrong.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
     
    Jack Klein, Nov 30, 2005
    #6
  7. Becker

    Skarmander Guest

    wrote:
    > Old Wolf wrote:
    >> Becker wrote:
    >>
    >>> 1.===========================================
    >>> /* a.c */
    >>> int x;
    >>> int y;
    >>>
    >>> void main()
    >>> {
    >>> f();
    >>> printf("%x %x\n", x, y);
    >>> }
    >>>
    >>> /* b.c */
    >>> double x;
    >>>
    >>> void f()
    >>> {
    >>> x = -0.0;
    >>> }

    >> All of your programs have undefined behaviour because there
    >> are two variables called 'x' with external linkage.
    >>

    >
    > The programs are rubbish of course. But wouldn't the file scope of x
    > mean that function f() is actually refering to the double x instead of
    > the int x?
    >

    Nope, because technically, there's no difference between the two.

    First of all, this program is in violation of:

    6.9-5 "If an identifier declared with external linkage is used in an
    expression [..], somewhere in the entire program there shall be exactly one
    external definition for the identifier; [..]"

    But suppose one of these was an "extern" declaration instead, so there was
    only one definition. Then we get:

    6.2.2-2 "In the set of translation units and libraries that constitutes an
    entire program, each declaration of a particular identifier with external
    linkage denotes the same object or function."

    So the "int x" and "double x" must be the same object. But of course that's
    not possible, and we are violating:

    6.2.7-2 "All declarations that refer to the same object or function shall
    have compatible type; otherwise, the behavior is undefined."

    Needless to say, int and double are not compatible types.

    Now, in *practice*, a compiler will indeed treat the 'x' in a.c and the 'x'
    in b.c as different objects within their respective scopes, compile the
    units as such, and then the linker will either notice a conflict (best
    case), create two separate objects (suboptimal but not completely awful
    case), or not notice anything at all and happily merge the storage for these
    incompatible objects (worst but unfortunately also most likely case).

    Try this: assign some nontrivial value to 'x' in 'f', try to compile and
    link the program, then run it if this works. You should see the value of the
    double (partially) reinterpreted as an int. Say hi to the nasal demons for
    me when you do this.

    This notwithstanding, a platform would actually be allowed to format your
    harddisk immediately after parsing both a.c and b.c, without paying any
    consideration to scope. The behavior is undefined; scope is irrelevant.

    S.
     
    Skarmander, Nov 30, 2005
    #7
  8. Becker

    Guest

    Jack Klein wrote:
    > On 29 Nov 2005 18:34:15 -0800, ""
    > <> wrote in comp.lang.c:
    > > The programs are rubbish of course. But wouldn't the file scope of x
    > > mean that function f() is actually refering to the double x instead of
    > > the int x?

    >
    > This is part of what I posted in a reply to the OP, but I'll repeat it
    > here for your benefit. The issue here is NOT file scope, but most
    > specifically IS external linkage:
    >
    > The C standard says this in "6.9 External definitions" paragraph 5:
    >
    > "An external definition is an external declaration that is also a
    > definition of a function (other than an inline definition) or an
    > object. If an identifier declared with external linkage is used in an
    > expression (other than as part of the operand of a sizeof operator
    > whose result is an integer constant), somewhere in the entire program
    > there shall be exactly one external definition for the identifier;
    > otherwise, there shall be no more than one."
    >
    > Violating a 'shall' outside of a constraint section is just plain old
    > ordinary undefined behavior. You have left planet C behind and
    > entered the Twilight Zone, and there is no right or wrong.
    >


    Yes I understand that. But I didn't think all globals are external
    linkage by default. I thought you need to use the 'extern' keyword for
    that. So, without extern globals with the same name have undefined
    behavior? I'm guessing that globals declared with the 'static' keyword
    can have the same name.
     
    , Nov 30, 2005
    #8
  9. said:

    > But I didn't think all globals are external
    > linkage by default. I thought you need to use the 'extern' keyword for
    > that.


    No. When you do this:

    extern int foo;

    you are saying "dear compiler, I promise to you that there is an object
    called foo, which is an int, but its storage is already reserved elsewhere
    so you don't need to reserve any; just trust me on this". Each translation
    unit needing to read or write foo (EXCEPT ONE) will need to have such a
    line. Typically, such lines are put into a header.

    In exactly one place in your program (at file scope), you must keep your
    promise:

    int foo;

    The translation unit that has this line need not have an extern int foo; as
    well (although it will do no harm if it does).

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
     
    Richard Heathfield, Nov 30, 2005
    #9
  10. Becker

    Guest

    Richard Heathfield wrote:
    > said:
    >
    > > But I didn't think all globals are external
    > > linkage by default. I thought you need to use the 'extern' keyword for
    > > that.

    >
    > No. When you do this:
    >
    > extern int foo;
    >
    > you are saying "dear compiler, I promise to you that there is an object
    > called foo, which is an int, but its storage is already reserved elsewhere
    > so you don't need to reserve any; just trust me on this". Each translation
    > unit needing to read or write foo (EXCEPT ONE) will need to have such a
    > line. Typically, such lines are put into a header.
    >
    > In exactly one place in your program (at file scope), you must keep your
    > promise:
    >
    > int foo;
    >
    > The translation unit that has this line need not have an extern int foo; as
    > well (although it will do no harm if it does).
    >


    Ah yes, quite right. Extern merely means "it's somewhere else" not
    "please export this". Thank you for reminding me.
     
    , Nov 30, 2005
    #10
  11. Becker

    Becker Guest

    Thanks all :)
    Yes, I understand now. The codes are full of undifined behaviors.
    And If I want to know why the results are like that, I should
    get to know how gcc treats those "undifined behaviors".

    PS: I get those programs from a forum :p
     
    Becker, Nov 30, 2005
    #11
  12. Jack Klein wrote:

    > Friends don't let friends void main().


    I like it! Looks like sig material to me.

    Allin Cottrell
     
    Allin Cottrell, Nov 30, 2005
    #12
  13. Becker

    Flash Gordon Guest

    wrote:
    > Old Wolf wrote:
    >> Becker wrote:
    >>
    >>> 1.===========================================
    >>> /* a.c */
    >>> int x;
    >>> int y;
    >>>
    >>> void main()
    >>> {
    >>> f();
    >>> printf("%x %x\n", x, y);
    >>> }
    >>>
    >>> /* b.c */
    >>> double x;
    >>>
    >>> void f()
    >>> {
    >>> x = -0.0;
    >>> }

    >> All of your programs have undefined behaviour because there
    >> are two variables called 'x' with external linkage.

    >
    > The programs are rubbish of course. But wouldn't the file scope of x
    > mean that function f() is actually refering to the double x instead of
    > the int x?


    No, both variable x have external linkage therefore the behaviour is
    undefined and on some systems, with some options, won't even link. If it
    does link the compiler is allowed to put both items in the same
    location, make that location the size of the smaller (probably int) and
    send a letter to you mother telling her you are dead. Alternatively the
    compiler/linker could place the two variables in separate locations and
    send a letter to the accounts department of the company you work for
    telling them to stop your salary. Anything it does is valid.
    --
    Flash Gordon
    Living in interesting times.
    Although my email address says spam, it is real and I read it.
     
    Flash Gordon, Nov 30, 2005
    #13
  14. Becker

    Becker Guest

    Flash Gordon wrote:
    >
    > No, both variable x have external linkage therefore the behaviour is
    > undefined and on some systems, with some options, won't even link. If it
    > does link the compiler is allowed to put both items in the same
    > location, make that location the size of the smaller (probably int) and
    > send a letter to you mother telling her you are dead. Alternatively the
    > compiler/linker could place the two variables in separate locations and
    > send a letter to the accounts department of the company you work for
    > telling them to stop your salary. Anything it does is valid.
    > --
    > Flash Gordon
    > Living in interesting times.
    > Although my email address says spam, it is real and I read it.


    hehe, I got it.
     
    Becker, Nov 30, 2005
    #14
    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. Harvey
    Replies:
    0
    Views:
    788
    Harvey
    Jul 16, 2004
  2. Harvey
    Replies:
    1
    Views:
    896
    Daniel
    Jul 16, 2004
  3. Replies:
    2
    Views:
    2,980
    Malcolm
    Aug 20, 2005
  4. Replies:
    2
    Views:
    325
    David Harmon
    Jan 3, 2007
  5. Replies:
    3
    Views:
    241
Loading...

Share This Page