1

I have a code which looks like this and executes completely fine,

#include <stdio.h>

int main( )
{
int i = 3, j = 4, k, l ;
k = addmult ( i, j ) ;
l = addmult ( i, j ) ;
printf ( "\n%d %d", k, l ) ;
}
int addmult ( int ii, int jj )
{
int kk, ll ;
kk = ii + jj ;
ll = ii * jj ;
return ( kk, ll ) ;
}

My question is that can we define a function afterwards without defining function prototype at the top and how can a function return two values?

Sahil Silare
  • 313
  • 2
  • 3
  • 15
  • Your function does not return two values. You should read about what the comma operator does. Also, in C if you don't have a prototype there is an implicit one that assumes you return an int. https://stackoverflow.com/questions/434763/are-prototypes-required-for-all-functions-in-c89-c90-or-c99 https://stackoverflow.com/questions/1737634/c-comma-operator – Retired Ninja Oct 27 '18 at 06:15
  • One should declare or prototype all the functions in respective headers before using them. Compile with `-Wstrict-prototypes` compiler will warn you about missing declaration of `addmult()`. Compile code with all warnings flags for e.g `gcc -Wall -Wpedantic -Wstrict-prototypes -Werror test.c` – Achal Oct 27 '18 at 06:16

1 Answers1

3

can we define a function afterwards without defining function prototype at the top

You can declare its proto in main. In your case, the function accepts ints and returns an int, so the default prototype (are they still alive in the Standard?) worked fine.

how can a function return two values?

  1. It can return a struct by-value:

    typedef struct { int first; int second; } int_pair;
    int_pair addmult(int x, int y) {
        return (int_pair){42, 314}; /* enough for the demo, lol (c) */
    }
    

    Or by-pointer:

    int_pair *addmult(int x, int y) {
        int_pair *retVal = malloc(sizeof(int_pair));
        return retVal->first = 42, retVal->second = 314, retVal;
    }
    int_pair *multadd(int x, int y) {
        static int_pair retVal{314, 42};
        return &retVal;
    }
    
  2. It can return a fresh array on the heap:

    /* 1. It is user's responsibility to free the returned pointer. */
    int *addmult(int x, int y) {
        int *retVal = malloc(2 * sizeof(int));
        return retVal[0] = 42, retVal[1] = 314, retVal;
    }
    
  3. Finally, it can return an array without allocating the latter on heap:

    /* 1. It is user's responsibility to NEVER free the returned pointer. */
    int *addmult(int x, int y) {
        static int retVal[] = {42, 314};
        return retVal;
    }
    

    In this case, the returned array can be reused (rewritten) by consequent calls so you should make use of its contents as soon as possible.

bipll
  • 11,747
  • 1
  • 18
  • 32
  • 1
    4) Since C99 you can return a compound literal: `return (int_pair){42, 314};` – David Ranieri Oct 27 '18 at 06:27
  • This is basically 1. but thank you, I was hoping something like this is possible. – bipll Oct 27 '18 at 06:29
  • 1
    Yes, is basically 1), just for completness ... :) – David Ranieri Oct 27 '18 at 06:31
  • 2
    "Default prototypes" are dead since C99. They actually never were a thing, but a function would be implicitly declared (without a prototype) as returning type `int` if it was encountered in a call in C90. But C99 stops that; every function (except `main()`) must be defined or declared before it is used. It still doesn't have to be declared with a prototype, but it is strongly recommended that you should always use an explicit prototype. – Jonathan Leffler Oct 27 '18 at 06:32
  • @JonathanLeffler Consequently, OP uses C90 (at most) so I was wondering. – bipll Oct 27 '18 at 06:34
  • @KeineLust For completeness, returning a pointer-to-struct should be noted. :) – bipll Oct 27 '18 at 06:35
  • 1
    Also the OP uses C90 at least; prototypes didn't exist in C before C90 (for all practical purposes). So, the code as written conforms (more or less) to C90. It doesn't do what's wanted, but that's a somewhat different problem. – Jonathan Leffler Oct 27 '18 at 06:36
  • @JonathanLeffler Means is the code logically incorrect if asked to point out? – Sahil Silare Oct 30 '18 at 03:01
  • @bipll: I don't see any advantage to `return retVal->first = 42, retVal->second = 314, retVal;` compared with `retVal->first = 42; retVal->second = 314; return retVal;` (spread over 3 lines for readability). Also, it is best not to declare any function prototypes inside another function — for all it is legal to do so. The declaration should be at file scope. – Jonathan Leffler Oct 30 '18 at 03:06
  • 1
    @SahilSilare: I'm not sure what you're asking. The `return(kk, ll);` does nothing useful in the code in the question (because that's a comma operator, so the first argument is evaluated for side effects — and there are none — and then the result is discarded). Hence, the value of `kk` is ignored, so the calculation is unnecessary, and an optimizing compiler will remove it. – Jonathan Leffler Oct 30 '18 at 03:10