-1

Hey I'm working on an exercise where I have to program an unsigned function in C, and I have a question, do I have to return something because of the type of the function?? Or is it optional??

2 Answers2

3

In normal use, any function declared to return a value ought to return a value. This is largely a matter of good programming practice. Failing to return a value is often a sign of an error. However, this is not required by the C standard, and there are two exceptions.

C 2018 6.9.1 12 allows a function to terminate by reaching the end of its code without returning a value, provided the caller does not use the value of the function:

Unless otherwise specified, if the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.

One case where a function might return a value in some situations and not in others is where it is designed to perform various different actions upon command. For example:

unsigned DoSomething(int command, int parameters[])
{
    switch (command)
    {
        case GetSomething:
            …
            return Something;
        case RememberSomething;
            Something = parameters[0];
            …
            break;
    }
}

Such designs may be error-prone and ought to be considered carefully. Since the function is declared to return a value, a programmer might expect it to do so and inadvertently assign the value of the function to another object in a situation where no value is returned, resulting in undefined behavior.

Additionally, a function may not return at all, and there is a function specifier for explicitly telling the compiler this is so, _Noreturn, as specified in 6.7.4. This behavior is typically used only in abnormal situations. For example, the standard functions abort and exit terminate the program, so they do not return. Of course, they are declared with void, so they never return anything. However, you might have a function that calls exit in some circumstances and returns an integer in others.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • `_Noreturn` is used to tell the compiler that a function being compiled will or may not return and so any return statement (e.g. `exit()`), present or not, may be discarded. It does __not__ say that when the function is used, there will be no return value. Neither is `_Noreturn` part of a prototype. Hence the caller does not know about the `_Noreturn`. – Paul Ogilvie Nov 01 '18 at 18:18
  • Hmm I'm not sure if the quoted statement actually **allows** a function not to return any values... – nodakai Nov 01 '18 at 18:20
  • @PaulOgilvie: What do you mean `_Noreturn` is not part of a prototype. It may be part of a function declaration whether or not it is a definition, is shown as such in some places in the standard, and hence is visible to the when used thusly. – Eric Postpischil Nov 01 '18 at 18:21
  • 1
    As far as the caller is concerned, a function declared as returning e.g. `int` will return an int _when_ it returns. So `exit()` is declared as `void`. – Paul Ogilvie Nov 01 '18 at 18:21
  • @PaulOgilvie: My answer does not say that `_Noreturn` says there will be no return value when the function is used. It is discussed in a paragraph discussing when the function does not return at all. – Eric Postpischil Nov 01 '18 at 18:21
  • @PaulOgilvie: `exit` is declared as a void, but a program may have a function that **does** return a value when it returns but that sometimes calls `exit`. Your comment appears to have missed this. I am answer OP’s question completely; they asked whether functions have to return something, and they did not exclude the case where the function does not return at all, so I am covering both the situation where the function returns and the situation where the function does not return in my answer. – Eric Postpischil Nov 01 '18 at 18:23
  • I mean that the compiler does not use the attribute when compiling a function that uses a function declared as `_Noreturn`. – Paul Ogilvie Nov 01 '18 at 18:24
  • @PaulOgilvie: Why would you think the compiler does not use the attribute? If we have `_Noreturn void foo(void); unsigned bar(int x) { if (x) { foo(); printf("Hello.\n"); } else return 0; }`, why would the compiler bother to put the `printf` or even `"Hello.\n"` in its output when they would never be used? I just tried it, and Apple LLVM 9.1.0, clang-902.0.39.2 omits them. – Eric Postpischil Nov 01 '18 at 18:27
  • OK Eric. I think the answer means that a function decalred to return something, must return that something. Only a void function does not return anything. Your exception implies that only a function declared to return something but that does not return at all, by implication does not even return that thing. – Paul Ogilvie Nov 01 '18 at 18:27
  • @PaulOgilvie: I have listed two exceptions. One is the function reaches its terminating `}`, upon which it returns to the caller without returning a value. The other is the function never returns to its caller. – Eric Postpischil Nov 01 '18 at 18:32
  • @Eric, The compiler may not assume `foo` will not return. The function specifiers `_Noreturn` and `inline` are not part of the type of a function, they are part of the declaration. See https://stackoverflow.com/questions/51746897/noreturn-in-a-struct-in-c-error-expected-specifier-qualifier-list-before-no and C11, 6.7.4.9:, which only requires a diagostic message but does not require anything when compiling a function using a `_Noreturn` function. – Paul Ogilvie Nov 01 '18 at 18:36
  • @nodakai: It permits it. A function call causes the function to be executed, which 6.9.1 11 says is done by executing the body of the function definition. That body is a *compound-statement*. When it is done, the function returns to its caller. Nothing in the C standard prohibits a function that returns a value from finishing its *compound-statement* by reaching the end of it rather than by executing a `return` statement. – Eric Postpischil Nov 01 '18 at 18:37
  • Reaching `}` of anon-void function without a return statement is an error/warning, right? – Paul Ogilvie Nov 01 '18 at 18:37
  • @PaulOgilvie: The question you point to asks about `_Noreturn` on a declaration of a function **pointer**, not on a declaration of a function. `_Noreturn` is permitted on a function declaration, as shown in the grammar at 6.7.4, and the constraints there do not say otherwise. Further, as I wrote, I just tested this in clang. `_Noreturn` was permitted, and it was used by the compiler to remove code that would never be executed. – Eric Postpischil Nov 01 '18 at 18:39
  • @PaulOgilvie: The C standard does not require a warning or error for a non-void function without a `return` statement. A compiler may choose to give warnings. – Eric Postpischil Nov 01 '18 at 18:41
  • 1
    @PaulOgilvie: The C standard licenses programs to discard code after a call to a `_Noreturn` function by the [“as if’ rule](https://stackoverflow.com/a/46455917/298225) and by 6.7.4 8, which says “A function declared with a `_Noreturn` function specifier shall not return to its caller.” – Eric Postpischil Nov 01 '18 at 18:44
  • @EricPostpischil ...but if it is part of the function type, then you can declare a pointer to a function to be of type `_Noreturn`, but you can't. – Paul Ogilvie Nov 01 '18 at 18:46
  • @PaulOgilvie: That has no relevance to my answer, as my answer does not discuss types of functions, at least in regard to `_Noreturn`. If you have questions about it, you can post a question to Stack Overflow. – Eric Postpischil Nov 01 '18 at 19:14
0

It is a good idea to have all your non-void functions return something, but if you exit a function without return statment (i.e. with the } character) and try to access its result, the behavior is undefined.

If you explore different compilers on Godbolt, with the following code as the C source:

int n()
{
    int a = 1234;
}

You will notice that some compilers issue a warning on this behavior depending on their warning levels.

The value you get if you try to use the result function as an int, for example, in printf("%d\n", n()); is undefined: there is no guarantee about what value you will get or if your program will crash, or do something else entirely.

That said, depending on the architecture you're compiling for, you may get a local value from your function as the return value. For example, on the x86 architecture, just about every calling convention specifies that the return value is whatever is in the register eax when the function returns. So, if the generated code for the function n above stores the local variable a in eax, the "return value" (quote-unquote) will be 1234.

This is not something you should ever rely on, though.

Govind Parmar
  • 20,656
  • 7
  • 53
  • 85