[DOMANDA] Come dichiarare una variabile valida sia come int,float,double.

  • Il Forum di Tom's Hardware, la più grande community dedicata all'Hardware e all'Informatica. Iscriviti Ora!
#1
Sto creando una libreria in linguaggio C
Dopo aver creato il file con estensione .h ho inserito i prototipi delle mie funzioni.
Poi mi sono domandato:
Voglio creare una funzione che faccia la somma di due numeri inseriti dunque io scrivo come prototipo:
void spinaci (double, double);
dunque mi pare chiaro che se dovessi usarla inserendo però variabili di tipo int potrebbe non funzionare.
viceversa se dovessi dichiarare un prototipo del tipo:

void spinaci (int, int);
e poi usare variabili di tipo double.


Ecco, potrei fare un cambio di tipologia di variabile nei futuri programmi che scriverò (tipo trasformo variabili di tipo double in int...se possibile… o viceversa), oppure creo più funzioni (spinaci1 spinaci2...) ciascuna con una diversa scelta dell'argomento. In entrambi i casi è piuttosto scomodo.
Mi chiedo come posso generalizzare la cosa, ossia definire una tipologia di variabile che vada d'accordo con tutte quelle che uso nei miei corsi universitari (int, double, float).
che faccio?
 

_Achille

Utente Attivo
2,886
652
Hardware Utente
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
Hard Disk
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
Scheda Video
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
Alimentatore
RM550X
Case
NZXT S340
Periferiche
Cooler Master XT; Razer Abyssus
Sistema Operativo
Windows 10 Pro
#2
Eheh. In C++ esiste l’overload di una funzione, per non parlare dei conseguenti Template.
In C ti crei manualmente tu le funzioni che ti servono. Certo che un intero è tranquillamente un float e un float è tranquillamente un double perciò puoi usare double per tutti.
 
Mi Piace: stex99.
429
265
Hardware Utente
CPU
Intel i7 6700HQ, 2.60Ghz, 4 core 8 threads
Scheda Madre
Asustek
Hard Disk
Hitachi 7200 rpm, 1TB
RAM
16GB DDR4 (2 slot su 4)
Scheda Video
Nvidia Geforce GTX 960M, 4GB
Scheda Audio
Realtek
Sistema Operativo
Windows 10 64bit
#3
Eh, stai toccando uno degli aspetti dolenti del C: non ci sono tipi generici.
Ovviamente puoi memorizzare un int in un double, in quanto la parte decimale verrebbe troncata (perdendo quindi l'informazione).

Oltre a duplicare il codice, e duplicare quindi le funzioni come suggerito da _Achille, rendendole però magari accessibili utilizzando lo stesso nome, e quindi decidere durante l'esecuzione quale chiamare, puoi sfruttare il preprocessore e lasciare a lui la scrittura delle diverse tipologie di funzioni...

Ho ipotizzato il calcolo della media di N valori (4 nel mio caso, per semplicità); non effettuo controlli sulla prima posizione dell'array, essendo solo un esempio.

C:
//
// name: templates.h
//

#define CONCAT(x, y) x ## y

#define get_average(T) CONCAT(get_average_, T)

TYPE get_average (TYPE) (TYPE * array, int len)
{
    TYPE sum = array[0];
    for(int i=0; i<len; i++)
        sum += array[i];
   
    return sum / len;
}
Uso la concatenazione dei token (quel ## sulla prima macro), nota anche come "token pasting". In sostanza concatena due token validi. Quindi l'altra macro, get_average, forma quello che è il nome completo della funzione, ad esempio: get_average_int, get_average_double etc etc.

C:
//
// main.c
//
#include<stdio.h>

#define TYPE int
#include "templates.h"
#undef TYPE

#define TYPE double
#include "templates.h"
#undef TYPE


int main()
{
    int    int_array[]    = {10,20,40,50};
    double double_array[] = {10.5, 20.5, 30.5, 33.5};
   
    int    avg_int    = get_average(int)(int_array, 4);
    double avg_double = get_average(double)(double_array, 4);
   
    printf("Media ints: %d\n", avg_int);
    printf("Media doubles: %f\n", avg_double);

    return 0;
}
Output:
Codice:
Media ints: 32
Media doubles: 26.375000
Dopo svariate correzioni, analizzando il preprocessore, sono riuscito a far funzionare qualcosa. Da notare comunque che nel sorgente è necessario includere l'header più volte impostando un TYPE differente.

Questo è il codice dopo l'espansione (è necessario compilare con gcc -E nome_file.c):
C:
# 5 "templates.h"
int get_average_int (int * array, int len)
{
    int sum = array[0];
    for(int i=0; i<len; i++)
        sum += array[i];

    return sum / len;
}
# 5 "generic.c" 2



# 1 "templates.h" 1




double get_average_double (double * array, int len)
{
    double sum = array[0];
    for(int i=0; i<len; i++)
        sum += array[i];

    return sum / len;
}
# 9 "generic.c" 2



int main()
{
    int int_array[] = {10,20,40,50};
    double double_array[] = {10.5, 20.5, 30.5, 33.5};

    int avg_int = get_average_int(int_array, 4);
    double avg_double = get_average_double(double_array, 4);

    printf("Media ints: %d\n", avg_int);
    printf("Media doubles: %f\n", avg_double);

    return 0;
}
 
Mi Piace: stex99.

Discussioni Simili