A value returned to a function without a `return' statement, why?

Discussion in 'C Programming' started by lovecreatesbeauty, Mar 14, 2005.

  1. I ever missed a `return' statement when write a function `int
    HighDigit(Num)' to get the highest digit of an integer.

    But even if the `return' statement is ignored the function still can
    obtain an `correct' return value when the argument `Num' is larger than
    or equal to the Macro `NUM_SYS'.

    If the argument is less than the Macro, the function without a `return'
    get an undefined value. I've made a test on Ms Windows 2000 and VC 6.


    Thank you in advance for explaining why.

    And would you please comment on this algorithm? Thank you.




    i.e.
    Num HighDigit(Num)
    ======================
    123 | 1
    321 | 3
    2 | 2
    10 | 1
    ______________________





    The code I write is:


    //highdigit.h

    #ifndef _HIGH_DIGIT_H_
    #define _HIGH_DIGIT_H_

    #define NUM_SYS 10 //number system, decimal assumed as default

    int HighDigit(int Num);

    #endif //_HIGH_DIGIT_H_


    //highdigit.c

    #include "highdigit.h"

    int HighDigit(int Num){
    while (Num >= NUM_SYS){
    Num /= NUM_SYS;
    }

    //return Num; //This statement be missed by me at first.
    }
    lovecreatesbeauty, Mar 14, 2005
    #1
    1. Advertising

  2. lovecreatesbeauty

    Jack Klein Guest

    On 13 Mar 2005 21:32:52 -0800, "lovecreatesbeauty"
    <> wrote in comp.lang.c:

    > I ever missed a `return' statement when write a function `int
    > HighDigit(Num)' to get the highest digit of an integer.


    It is actually legal in C to omit a return statement from a function
    with a return type other than void. Rather foolish, but legal.

    > But even if the `return' statement is ignored the function still can
    > obtain an `correct' return value when the argument `Num' is larger than
    > or equal to the Macro `NUM_SYS'.


    Now here the C standard does have something to say. If you miss a
    return statement in a function that has a non-void return type, and if
    the calling code uses the return value in any way, then the behavior
    is undefined.

    > If the argument is less than the Macro, the function without a `return'
    > get an undefined value. I've made a test on Ms Windows 2000 and VC 6.


    Actually the result is always undefined, a term with a precisely
    defined meaning in the C language. It is just in some cases the value
    is what you expect it to be, and in other cases it is not.

    > Thank you in advance for explaining why.


    When you produce undefined behavior, the C language no longer
    specifies what will happen. One possible result of undefined behavior
    is that, in some cases, the program "works" the way you think it
    should.

    > And would you please comment on this algorithm? Thank you.
    >
    >
    >
    >
    > i.e.
    > Num HighDigit(Num)
    > ======================
    > 123 | 1
    > 321 | 3
    > 2 | 2
    > 10 | 1
    > ______________________
    >
    >
    >
    >
    >
    > The code I write is:
    >
    >
    > //highdigit.h
    >
    > #ifndef _HIGH_DIGIT_H_
    > #define _HIGH_DIGIT_H_


    This is something you should not do. All identifiers beginning with
    two underscores or an underscore followed by an uppercase letter are
    reserved for the compiler, and not to be used in your code.

    > #define NUM_SYS 10 //number system, decimal assumed as default


    Either your function always works with base 10, in which case you
    don't need the definition in the header but only in the source code
    file with the function body. And it is not a default, it is the only
    value. Or you want it to work on various bases, in which case the
    base should be a function parameter as in functions like strtol() in
    the standard library.

    > int HighDigit(int Num);


    You could make this:

    int HighDigit(int Num, int base);

    > #endif //_HIGH_DIGIT_H_
    >
    >
    > //highdigit.c
    >
    > #include "highdigit.h"
    >
    > int HighDigit(int Num){
    > while (Num >= NUM_SYS){
    > Num /= NUM_SYS;
    > }
    >
    > //return Num; //This statement be missed by me at first.
    > }


    ....and likewise:

    int HighDight(int Num, int base)
    {
    assert(base > 0);
    while (Num >= base)
    {
    Num /= base;
    }
    return Num;
    }

    --
    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, Mar 14, 2005
    #2
    1. Advertising

  3. Jack, thank you. Could please give some suggestion on the usage of
    `assert()'.

    I think, an runtime value makes assert() failed in debug version can
    also (always) make it failed in release version, but in the release
    version (NDEBUG defined) the `assert()' means null, so it can't catch
    runtime error in release version.
    lovecreatesbeauty, Mar 14, 2005
    #3
  4. "Jack Klein" <> wrote in message
    news:...
    > On 13 Mar 2005 21:32:52 -0800, "lovecreatesbeauty"
    > <> wrote in comp.lang.c:
    > > Thank you in advance for explaining why.

    >
    > When you produce undefined behavior, the C language no longer
    > specifies what will happen. One possible result of undefined behavior
    > is that, in some cases, the program "works" the way you think it
    > should.


    As to why the UB leads to it "working" in his case (as the OP asked), it may
    be because the compiler happened to use the same register for "Num" that is
    also the return value register. Of course, recompiling with a different
    compiler, version, or optimization level may cause a different register to
    be used and complete garbage to be returned. UB at its best.

    S

    --
    Stephen Sprunk "Stupid people surround themselves with smart
    CCIE #3723 people. Smart people surround themselves with
    K5SSS smart people who disagree with them." --Aaron Sorkin
    Stephen Sprunk, Mar 14, 2005
    #4
  5. lovecreatesbeauty

    Jack Klein Guest

    On 14 Mar 2005 04:13:24 -0800, "lovecreatesbeauty"
    <> wrote in comp.lang.c:

    > Jack, thank you. Could please give some suggestion on the usage of
    > `assert()'.
    >
    > I think, an runtime value makes assert() failed in debug version can
    > also (always) make it failed in release version, but in the release
    > version (NDEBUG defined) the `assert()' means null, so it can't catch
    > runtime error in release version.


    C doesn't define "debug version" and "release version". If you want
    the assert() macro to work, make sure that NDEBUG is not defined. If
    you can't figure out how to modify your IDE's settings, ask in one of
    Microsoft's support groups in the news:microsoft.public.* family on
    their server msnews.microsoft.com.

    --
    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, Mar 15, 2005
    #5
  6. >original question

    >//highdigit.h
    >
    >#ifndef HIGH_DIGIT_H
    >#define HIGH_DIGIT_H
    >
    >#define NUM_SYS 10 //
    >
    >int HighDigit(int num);
    >
    >#endif //HIGH_DIGIT_H



    >//highdigit.c
    >
    >#include "highdigit.h"
    >
    >int HighDigit(int num){
    > while (num >= NUM_SYS){
    > num /= NUM_SYS;
    > }
    >
    > //return num; //omitted.
    >}



    I test it on Linux & GCC again, and get the same problem as on Windows
    & VC6.

    If the argument `num' is larger than or equal to the Macro, the loop
    body is executed and the result is right as if the `return num'
    provided implicitly. But if the argument is less than the Macro, the
    loop body is not executed. The result is undefinded.


    Especially, when I use Jack's revised version (ignore the `return'
    statement).

    int HighDigit(int num, int base){
    while (num >= base){
    num /= base;
    }

    //return num; //omitted still
    }

    The result is always correct even if `num' is less than `base', and the
    loop body is not executed also when `num' is less than `base'.


    I don't konw `UB', `OP', `register' which Stephen Sprunk mentioned.
    Could you please give me more help? Thank you.
    lovecreatesbeauty, Mar 15, 2005
    #6
  7. lovecreatesbeauty

    Grumble Guest

    Re: A value returned to a function without a `return' statement,why?

    lovecreatesbeauty wrote:

    > I don't konw `UB', `OP', `register' which Stephen Sprunk mentioned.


    UB = Undefined Behavior
    OP = Original Poster (in this case: you)
    register = http://en.wikipedia.org/wiki/Processor_register
    Grumble, Mar 15, 2005
    #7
  8. Re: A value returned to a function without a `return' statement,why?

    "lovecreatesbeauty" <> writes:
    >>original question

    >
    >>//highdigit.h
    >>
    >>#ifndef HIGH_DIGIT_H
    >>#define HIGH_DIGIT_H
    >>
    >>#define NUM_SYS 10 //
    >>
    >>int HighDigit(int num);
    >>
    >>#endif //HIGH_DIGIT_H

    >
    >
    >>//highdigit.c
    >>
    >>#include "highdigit.h"
    >>
    >>int HighDigit(int num){
    >> while (num >= NUM_SYS){
    >> num /= NUM_SYS;
    >> }
    >>
    >> //return num; //omitted.
    >>}

    >
    >
    > I test it on Linux & GCC again, and get the same problem as on Windows
    > & VC6.
    >
    > If the argument `num' is larger than or equal to the Macro, the loop
    > body is executed and the result is right as if the `return num'
    > provided implicitly. But if the argument is less than the Macro, the
    > loop body is not executed. The result is undefinded.


    The result is *always* undefined. The undefined result may, in some
    cases, happen to be what you expect it to be. You should never depend
    on this; the behavior can vary depending on anything, including the
    phase of the moon or the importance of the customers watching your
    demo.

    --
    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 15, 2005
    #8
  9. On 15 Mar 2005 04:10:20 -0800, "lovecreatesbeauty"
    <> wrote:
    >I test it on Linux & GCC again, and get the same problem as on Windows
    >& VC6.


    It is working by accident. The compiler has (apparently) chosen to use
    the same register for the calculation as it uses to return a value. This
    is a pretty good strategy, and a common optimization. Change the code to
    increment the value of a global variable and you'll likely get different
    results.

    I strongly suggest you turn up the warning level on your compiler - it
    should be telling you about the error in your function.

    --
    #include <standard.disclaimer>
    _
    Kevin D Quitt USA 91387-4454 96.37% of all statistics are made up
    Per the FCA, this address may not be added to any commercial mail list
    Kevin D. Quitt, Mar 15, 2005
    #9
    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. Seong-Kook Shin
    Replies:
    1
    Views:
    482
    Richard Bos
    Jun 18, 2004
  2. Mr. SweatyFinger

    why why why why why

    Mr. SweatyFinger, Nov 28, 2006, in forum: ASP .Net
    Replies:
    4
    Views:
    862
    Mark Rae
    Dec 21, 2006
  3. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,761
    Smokey Grindel
    Dec 2, 2006
  4. Greenhorn
    Replies:
    15
    Views:
    797
    Keith Thompson
    Mar 6, 2005
  5. lovecreatesbeauty
    Replies:
    0
    Views:
    271
    lovecreatesbeauty
    Mar 14, 2005
Loading...

Share This Page