У меня есть код, который выглядит вот так и работает нормально,
#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 ) ;
}
Мой вопрос в том, можем ли мы определить функцию после этого, не определяя прототип функции вверху, и как функция может возвращать два значения?
Перед использованием необходимо объявить или прототипировать все функции в соответствующих заголовках. Компилятор с -Wstrict-prototypes
предупредит вас об отсутствии объявления addmult()
. Скомпилируйте код со всеми флагами предупреждений, например, для gcc -Wall -Wpedantic -Wstrict-prototypes -Werror test.c
can we define a function afterwards without defining function prototype at the top
Вы можете объявить его прото в main
. В вашем случае функция принимает int
и возвращает int
, поэтому прототип по умолчанию (живы ли они в Стандарте?) Работал нормально.
how can a function return two values?
Он может возвращать структуру по значению:
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) */
}
Или по указателю:
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;
}
Он может вернуть свежий массив в куче:
/* 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;
}
Наконец, он может возвращать массив, не размещая его в куче:
/* 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;
}
В этом случае возвращенный массив может быть повторно использован (переписан) последовательными вызовами, поэтому вы должны использовать его содержимое как можно скорее.
4) Начиная с C99, вы можете возвращать составной литерал: return (int_pair){42, 314};
Это в основном 1. но спасибо, я надеялся, что что-то подобное возможно.
Да, в основном 1), для полноты картины ... :)
"Прототипы по умолчанию" мертвы с C99. На самом деле они никогда не существовали, но функция была бы неявно объявлена (без прототипа) как возвращающая тип int
, если бы она встречалась при вызове в C90. Но C99 останавливает это; каждая функция (кроме main()
) должна быть определена или объявлена перед использованием. Его по-прежнему необязательно объявлять с прототипом, но настоятельно рекомендуется всегда использовать явный прототип.
@JonathanLeffler Следовательно, OP использует C90 (максимум), поэтому мне было интересно.
@KeineLust Для полноты следует отметить возврат указателя на структуру. :)
Также OP использует по крайней мере C90; прототипов не существовало в C до C90 (для всех практических целей). Итак, написанный код соответствует (более или менее) C90. Он не делает то, что нужно, но это несколько другая проблема.
@JonathanLeffler Значит, код является логически неверным, если его просят указать?
@bipll: Я не вижу преимуществ return retVal->first = 42, retVal->second = 314, retVal;
по сравнению с retVal->first = 42; retVal->second = 314; return retVal;
(разнесен на 3 строки для удобочитаемости). Кроме того, лучше не объявлять какие-либо прототипы функций внутри другой функции - это законно. Объявление должно находиться в области видимости файла.
@SahilSilare: Я не уверен, о чем вы спрашиваете. return(kk, ll);
не делает ничего полезного в коде вопроса (потому что это оператор запятой, поэтому первый аргумент оценивается на предмет побочных эффектов - а их нет - а затем результат отбрасывается). Следовательно, значение kk
игнорируется, поэтому в вычислении нет необходимости, и оптимизирующий компилятор удалит его.
Ваша функция не возвращает двух значений. Вы должны прочитать о том, что делает оператор запятой. Кроме того, в C, если у вас нет прототипа, есть неявный, который предполагает, что вы возвращаете int. stackoverflow.com/questions/434763/…stackoverflow.com/questions/1737634/c-comma-operator