2015-02-24 16 views
14

Ho una funzione di prendere una statica matrice bidimensionale e trattare gli elementi degli elementi della matrice come costante:tipi di puntatore non compatibili e constness

void test_function(const char arr[3][3]); 

Sto cercando di chiamare una funzione come segue :

char my_var[3][3] = { {0, 0, 0}, {0, 0, 0}, {0, 0, 0} }; 
test_function(my_var); 

Quando si compila con GCC (senza bandiera), ottengo il seguente avvertimento:

test.c:9:8: warning: passing argument 1 of 'test_function' from incompatible pointer type 
    test_function(my_var); 
       ^
test.c:4:6: note: expected 'const char (*)[3]' but argument is of type 'char (*)[3]' 
void test_function(const char arr[3][3]); 

Se rimuovo il prototipodal prototipo test_function, l'avviso scompare. Ma non è proprio quello che voglio.

Durante la compilazione con clang con sia -pedantic-errors e -Wall Non ricevo alcun avviso sull'incompatibilità del puntatore.

Vorrei solo capire perché gcc emette un avviso di questo tipo in questo caso. Perché i miei indicatori/array potrebbero essere incompatibili?

+0

Voglio dire che questo è un bug di GCC - il fatto che Clang non produca alcuna diagnosi mi rende piuttosto sospetto. A proposito, dovresti notare che in realtà è un avvertimento, non un errore (sembra che tu stia compilando con '-Werror'). – nneonneo

risposta

10

GCC è giusto alla lettera della norma e Clang è sbagliato.

6.3.2.3/2:

Per qualsiasi qualificazione q, un puntatore ad un tipo non-q-qualificato può essere convertito in un puntatore alla versione q Qualificato del tipo ;

Sembra molto promettente. Ma aspetta.

6.2.5/26:

Un tipo derivato non è condizionata dalle qualificazioni (se presente) del tipo da cui deriva

Questa disposizione della norma come applicata in particolare per gli array non è necessario, e potrebbe essere facilmente invertito. Cioè, const char[3] potrebbe essere facilmente realizzato con una versione const-qualified di char[3]. Ma non è. Sono solo tipi diversi e incompatibili. Di fatto non ci sono tipi di array con qualifica costante in C, quindi non è possibile avere una versione con qualifica const di char[3]. Questo è lo standard che abbiamo e dobbiamo convivere.

+1

Allora perché gcc non emette un avvertimento nel caso di una funzione che assume 'const char [3]' come parametro e passa una variabile di tipo 'char [3]'? –

+4

Poiché 'const char [3]' come parametro di funzione è una bugia. È trattato silenziosamente come 'const char *'. L'argomento attuale è decaduto in un 'char *'. Quindi l'intera attività è coperta da 6.3.2.3/2 che ho citato. –

5

Dalle C-FAQ [Question 11.10]

In C, se si deve assegnare o passare puntatori che hanno qualificazione mismatch al diverso dal primo livello di indirezione, è necessario utilizzare cast espliciti (ad esempio, (const char **) in questo caso), anche se come sempre, la necessità di un cast di questo tipo può indicare un problema più profondo che il cast non risolve in realtà .

Nel tuo caso:

test_function((const char (*)[3])my_var); 
Problemi correlati