L'inusuale dichiarazione proposta è in effetti supportata dallo standard ANSI/ISO (INCITS) C 1999 in alcuni casi ben definiti, e risulta già chiara nel relativo
draft pubblicamente disponibile.
Si veda in particolare l'esempio 5 a pagina 120 (corrispondente alla pagina 130 del PDF, i.e. CTRL+N "130") nella sezione 6.7.5.3 "Function declarations, including prototypes" del draft citato.
EXAMPLE 5 - The following are all compatible function prototype declarators.
double maximum(int n, int m, double a[n][m]);
double maximum(int n, int m, double a[*][*]);
double maximum(int n, int m, double a[ ][*]);
double maximum(int n, int m, double a[ ][m]);
La specifica C'99 ha inopinatamente resuscitato, come effetto collaterale della introduzione ufficiale dei VLA (variable length array), un potente generatore di errori ed incongruenze di cui la ANSI/ISO C++ 1997 aveva tentato di liberarsi informalmente e con ampio supporto materiale (
vector e derivate).
D'altro canto, parlando di DSP, chiunque conosca Numerical C dalla sua nascita sa bene che:
a) Proprio i VLA sono da sempre una delle caratteristiche salienti delle estensioni introdotte da GCC (da cui deriva appunto Numerical C) !
b) Lo standard C'99 ha accolto la quasi totalità dei nuovi costrutti GNU/Numerical C (numeri complessi, nuova sintassi per gli array, VLA etc.).
c) Una parte consistente del manuale del compilatore VisualDSP++ (come quelli della quasi totalità di cross-compilatori embedded) è dedicata a descrivere le innumerevoli estensioni e variazioni rispetto allo standard ANSI/ISO C++ 1997, tra le quali ve ne sono alcune specifiche per inizializzatori non costanti e per la compatibilità esplicita con GCC.
Queste osservazioni storiche spiegano perfettamente l'ampio supporto dei compilatori GCC a quei costrutti alquanto inusuali:
la loro introduzione come features proprietarie si deve proprio a tali compilatori.
Il recepimento nello standard è avvenuto molti anni dopo.
Detto questo, si deve comunque ricordare che nell'antecedente standard ANSI/ISO 1997 relativo a C++ (un draft recente è pubblicamente disponibile
qui) non si fa minimamente menzione di tale forma.
A fortiori, riassumendo lo Stroustrup
(1) che di tale standard è l'ispiratore, il padre e l'artefice:
Le espressioni sintatticamente valide in C++ per una dichiarazione di funzione che impieghi array old style con subscritti espliciti con singola omissione sono
fn(array[])
e
fn(array[][B]..[Z])
nella seconda forma B..Z sono tutte
COSTANTI NOTE A TEMPO DI COMPILAZIONE, ossia combinazioni arbitrarie di una o più delle seguenti tipologie:
- Costanti numeriche intere esplicite;
- Costanti simboliche dichiarate tramite
const (unsigned) int o idiomi equivalenti;
- Interi positivi (naturali non nulli) dichiarati indirettamente tramite #define (pessima pratica di programmazione, ma formalmente corretta).
Riguardo al range ammissibile, le costanti di cui sopra saranno obbligatoriamente tutte risolvibili a compile time come
interi positivi.
Si veda anche
questo esempio, che fa appunto uso di
const.
Il metodo formalmente consigliato dal
creatore del linguaggio C++ per l'impiego di array dinamici come parametri, unico metodo ufficialmente previsto in C++ '97, è
il passaggio del puntatore accompagnato da un int per ogni dimensione dell'array.
Come noto, il nome stesso dell'array è un puntatore implicito dal contenuto costante, in quanto coincide funzionalmente quasi ovunque con il puntatore al primo elemento dell'array, con restrizioni solo sull'uso come Lvalue. Si tratta inoltre dell'unico tipo di dato predefinito per il quale, dato un array A, l'espressione logica (A == &A) venga valutata come TRUE. La scrittura &A è formalmente corretta, sebbene del tutto priva di effetto ed equivalente al semplice nome dell'array.
Bjarne specifica inoltre che, se si vuole realmente impiegare C++ come OOL "moderno", robusto, portabile, manutenibile, nei limiti consentiti dal linguaggio (alla fin dei conti non si parla di Eiffel o Smalltalk), è ampiamente preferibile dimenticarsi gli array C-style ed impiegare direttamente vector, valarray, list, string. Gli array multidimensionali C-style sono effettivamente considerati legacy per C++, nello Stroustrup ed in quasi tutta la letteratura subordinata e derivata, inclusi gli standard interni per la codifica derivati da raccomandazioni normative della massima autorevolezza come DO178A/B, D6-35071, ESA PSS05, MISRA/C++ e simili.
Nessuna meraviglia, quindi, che alcuni compilatori C/C++ anche molto recenti possano richiedere l'uso di switch e/o direttive #pragma per supportare appieno una sintassi di fatto peculiare del C'99, o magari scegliere di non supportarla affatto, vista la presenza di alternative stilisticamente più pulite e meno error-prone in C++.
In definitiva, un simile stile di dichiarazione è effettivamente standard per il C'99, ma non lo è per C++ '97 né per il "classico" C'89.
(1) "The C++ Programming language, 3rd ed.", Addison Wesley 1997, pag. 838 e seguenti.