Как можно сделать, возврат разного типа переменной 'int, float' из функции на си?
Есть у меня функция 'popStack' которая должна возвращать в зависимости от типа float или int.
float popStack(void);
int popStack(void);
int - 4 байта; float - 4 байта;
Ответы (3 шт):
Если смотреть стандарт языка С, то там написано (Working Draft, 1997-11-21, WG14/N794 J11/97-158) в разделе 6.7.1 :
3 The return type of a function shall be void or an object type other than array type.
Т.е. можно возвращать любой тип, кроме массива. Но, на самом деле, толку от этого не много, т.к. можно возвращать значение любого, но одного типа.
Ну вот такой пример:
#include <stdio.h>
typedef union {
float x;
int n;
} flint;
flint z;
flint popStack(void) {
return z;
}
int main(int argc, char *argv[]) {
int j;
float r;
flint fl;
z.x = 25.5;
fl = popStack();
printf("%6.2f\n", fl.x);
z.n = 25;
fl = popStack();
printf("%6d\n", fl.n);
}
Вывод этой программы будет таким:
$ ./a.out
25.50
25
Вроде бы - да, возвращается и целое значение и плавающее... Только пользоваться этим всё равно - не удобно!
Что-то вроде псевдо перегрузки, но все равно нужно передавать параметр c11:
#include <stdio.h>
float popStack_f(void) {
return 1.0f;
}
int popStack_i(void) {
return 6;
}
#define popStack(X) _Generic((X), \
int: popStack_i, \
float: popStack_f)()
int main(void) {
printf("%d\n", popStack((int)0));
printf("%f\n", popStack((float)0));
return 0;
}
6
1.000000
Возвращаемое значение должно быть одного типа. Но если хочется, то можно сделать виртуальный класс чисел.
// gcc -Wall -Wextra -Wpedantic -std=c11 virtualplus.c -o virtualplus
enum {
virtualNumberInt = 0 ,
virtualNumberFloat = 1
} ;
typedef
struct virtualNumber {
int type ;
union {
int i ;
float f ;
} ;
} virtualNumber ;
# include <setjmp.h>
jmp_buf jbexception ;
virtualNumber plus (virtualNumber x,virtualNumber y){
switch(x.type){
case virtualNumberInt :
switch(y.type){
case virtualNumberInt :
return (virtualNumber){
.type = virtualNumberInt ,
.i = x.i + y.i } ;
case virtualNumberFloat :
return (virtualNumber){
.type = virtualNumberFloat ,
.f = x.i + y.f } ;
default :
longjmp(jbexception,1); }
case virtualNumberFloat :
switch(y.type){
case virtualNumberInt :
return (virtualNumber){
.type = virtualNumberInt ,
.f = x.f + y.i } ;
case virtualNumberFloat :
return (virtualNumber){
.type = virtualNumberFloat ,
.f = x.f + y.f } ;
default :
longjmp(jbexception,1); }
default :
longjmp(jbexception,1); }
}
#include <stdio.h>
#include <stdlib.h>
int main(){
if(setjmp(jbexception)) {
fputs("exception: wrong number type",stderr);
exit(1); }
virtualNumber x = {.type = virtualNumberInt , .i = 1};
virtualNumber y = {.type = virtualNumberFloat , .f = 1.0};
virtualNumber z = plus(x,y);
switch(z.type){
case virtualNumberInt :
printf("z(int)=%d\n",z.i);
break;
case virtualNumberFloat :
printf("z(float)=%f\n",z.f);
break;
default :
longjmp(jbexception,1); }
}
проверка :
$ ./virtualplus
z(float)=2.000000