Perché avvertire in C e impossibile compilare in C ++?
-
10-07-2019 - |
Domanda
Perché questo codice
int (*g)(int);
int (*h)(char);
h = g;
In C, dammi tale avviso durante la compilazione:
"avviso: assegnazione da un tipo di puntatore incompatibile"
In C ++, non è possibile compilare.
Soluzione
I prototipi non corrispondono. g
è un puntatore a una funzione che accetta un int
e restituisce un int
mentre h
è un puntatore a un funzione che accetta un char
e restituisce un int
. Sono due tipi separati e quindi l'avvertimento (assegnazione delle mele alle arance).
Altri suggerimenti
I due puntatori di funzioni non hanno la stessa firma, poiché i parametri di input sono diversi.
I puntatori a funzione restituiscono entrambi un int , mentre g accetta un int come input e h accetta un carattere come parametri di input.
Anche se a volte puoi mescolare int e char , stai mescolando i puntatori a funzione, quindi il compilatore ti avvisa correttamente che potresti fare qualcosa di sbagliato.
Codice di esempio:
#include <stdio.h>
int gf(int n)
{
return printf("gf(%d)\n", n);
}
int hf(char c)
{
return printf("hf('%c')\n", c);
}
int main()
{
int (*g)(int) = gf; // pointer to gf
int (*h)(char) = hf; // pointer to hf
g = h; // warning: possibly incompatible functions
g(65); // cast 65 to char and call h
return 0;
}
Compilazione:
$ gcc-4.exe -Wall a.c
a.c: In function 'main':
a.c:18: warning: assignment from incompatible pointer type
Programma in esecuzione:
$ ./a.exe
hf('A')
Come vedi, in C, funziona bene, ma il compilatore ti dà un avviso adeguato. Se proviamo a compilare questo come codice C ++, il compilatore non accetterà il nostro giocoleria puntatore:
$ g++-4.exe a.c
a.c: In function 'int main()':
a.c:18: error: invalid conversion from 'int (*)(char)' to 'int (*)(int)'
Uno è dichiarato che punta a una funzione che accetta un int
, l'altro - a una funzione che accetta un char
. Quelle sono firme diverse, quindi i puntatori sono incompatibili.
Hai dichiarato g come una funzione che prende un argomento di tipo int e restituisce un int, e h come una funzione che prende un argomento di tipo char e restituisce un risultato int. Le firme delle due funzioni non sono intercambiabili e quindi non è possibile assegnare da un puntatore a uno a un puntatore all'altro.
Hai dichiarato geh come funzioni. In realtà, il mio compilatore fornisce l'errore "lvalue richiesto come operando di sinistra dell'assegnazione", e sembra strano che tu possa ottenere questo codice da compilare con un solo avvertimento?
EDIT: originariamente, il codice nella domanda dichiarava ge h come funzioni. Ora sono stati cambiati in puntatori a funzione, che in effetti daranno solo un avvertimento.
Perché stai assegnando puntatori incompatibili. Un puntatore a funzione accetta un intero con segno come argomento, l'altro carattere (la firma dipende dal sistema). Anche se entrambi restituiscono lo stesso, sono abbastanza diversi.
Ignora gli avvisi, usa i puntatori di funzione (mentre esegui il casting per renderlo effettivamente compilato) e vedrai cosa intendo :)
Poiché le firme delle funzioni sono diverse, non si tratta di C legale o C ++ legale. La domanda è: perché i compilatori la trattano diversamente. In nessuno degli standard c'è molta guida su cosa fare con i programmi che violano lo standard, tranne per il fatto che alcune violazioni richiedono una diagnostica (ed entrambi questi casi forniscono un messaggio diagnostico). Gli standard riguardano normalmente cos'è un programma C o C ++ valido e cosa deve fare l'implementazione quando ne viene dato uno.
C è un linguaggio notevolmente più vecchio di C ++, e un sacco di codice C è stato scritto su compilatori molto meno rigidi di quelli esistenti al giorno d'oggi. Il C ++ è stato più rigoroso dall'inizio, quindi il codice C ++ pre-standard tende ad essere un codice C ++ standard valido che semplicemente non utilizza determinate funzionalità.
Per questo motivo, è più probabile che un compilatore C sia clemente rispetto a un compilatore C ++, supponendo che i compilatori siano stati scritti per uso pratico. Dopotutto, c'è molto codice C che assume allegramente cose come questa, e alcune di queste sono molto utili, ma lo stesso non è vero per C ++.
Quello che posso aggiungere è che la corrispondenza delle funzioni in C è diversa da quella in C ++. In C si utilizza solo il nome (pertanto non è possibile sovraccaricare i parametri). In C ++ ogni funzione ha una "firma" diversa, composta dai parametri. (Hanno dovuto rendersi conto del sovraccarico dei parametri.)