Perché le matrici non possono essere passate come argomenti di funzione in C?


12

A seguito di questo commento , ho cercato di google perché, ma il mio google-fu fallito.

Commento dal link:

[...] Ma la cosa importante è che gli array e i puntatori sono cose diverse in C.

Supponendo che non si stia utilizzando alcuna estensione del compilatore, in genere non è possibile passare un array stesso a una funzione, ma è possibile passare un puntatore e indicizzare un puntatore come se fosse un array.

Ti stai effettivamente lamentando che i puntatori non hanno lunghezza allegata. Dovresti lamentarti del fatto che le matrici non possono essere passate come argomenti di funzione o che le matrici si degradano implicitamente in puntatori.


Non sono sicuro che sia la risposta, ma parte del tipo di un array è la sua dimensione, quindi credo che dovresti definire una funzione per ogni dimensione che vuoi accettare.
clcto

Intendi come puntatori a funzioni ? Si prega di chiarire la domanda.
user949300,

2
@ user949300 No, dal contesto del commento è abbastanza chiaro; non è possibile passare un array a una funzione perché diventa un puntatore e vuole sapere perché è così.
Doval,

@DocBrown rlemon ha proposto una modifica per questo.
Florian Margaine,

Risposte:


18

La mia prima ipotesi per il motivo era semplicemente per motivi di prestazioni e di risparmio della memoria, e anche per la facilità di implementazione del compilatore (specialmente per il tipo di computer al momento dell'invenzione di C). Il passaggio di matrici enormi "per valore" sembrava avere un impatto enorme sullo stack, ha bisogno di un'operazione di copia dell'array completa per ogni chiamata di funzione e probabilmente il compilatore deve essere più intelligente per produrre il codice assembly corretto (anche se l'ultimo punto è discutibile) . Sarebbe anche più difficile trattare gli array allocati dinamicamente allo stesso modo degli array allocati staticamente (dal punto di vista della sintassi del linguaggio).

EDIT: dopo aver letto alcune parti da questo collegamento , Credo la vera ragione (e la ragione per cui matrici in structs vengono trattati come tipi di valore, mentre le matrici suola non sono) è la compatibilità all'indietro di C predecessore B . Ecco la citazione di Dennis Ritchie:

[...} La soluzione ha costituito il salto cruciale nella catena evolutiva tra BCPL senza tipo e tipizzato C. Ha eliminato la materializzazione del puntatore in memoria e ha invece causato la creazione del puntatore quando il nome dell'array è menzionato in un'espressione. La regola, che sopravvive nella C odierna, è che i valori di tipo array vengono convertiti, quando compaiono in espressioni, in puntatori al primo degli oggetti che compongono l'array.

Questa invenzione ha permesso alla maggior parte del codice B esistente di continuare a funzionare, nonostante il cambiamento di base nella semantica del linguaggio. [..]


5
A struct Foo { int array[N]; } può essere passato per valore. E l'ultima parte del trattamento delle allocazioni dinamiche e statiche sembra la stessa (un array nel senso più stretto include sempre una dimensione, i concetti unificanti per cose come l'indicizzazione dell'array sono puntatori accoppiati con il decadimento array-to-pointer), potresti elaborare?

@delnan: Penso che i principi generali qui indicati siano validi. Chiaramente, se avvolgi l'array in una struttura, stai specificando le tue intenzioni. Nel caso generale, passerai quasi sempre per riferimento.
Robert Harvey,

Trovo anche il commento a cui si fa riferimento nel PO inutilmente pedante. Chiaramente stai passando un puntatore anziché un array per valore. Ciò che è ugualmente vero, tuttavia, è che stai effettivamente passando un array per riferimento. Se l'obiezione è che non c'è lunghezza allegata, è abbastanza facile passare anche quello.
Robert Harvey,

@RobertHarvey Questa è ancora un'asimmetria nel sistema dei tipi: tutto viene passato per valore, tranne i tipi di array (anche se gli array che fanno parte di un tipo di struttura vengono passati per valore) e utilizza persino la stessa identica notazione (entrambi nel sito di chiamata e nella firma della funzione).

@delnan: Perché è rilevante, a parte quello che devi ricordare?
Robert Harvey,

9

Un minicomputer PDP con solo 8 kB di memoria non può allocare uno stack molto grande. Quindi, su una macchina del genere, bisogna stare attenti in una progettazione (o evoluzione) del linguaggio per essere in grado di ridurre al minimo ciò che deve andare in pila per l'utilizzo previsto delle chiamate di subroutine comuni. C è ancora oggi utilizzato per programmare sistemi embedded estremamente limitati dalla memoria (pochi kB), quindi il compromesso è generalmente buono.

Su un'architettura di processore che ha pochissimi registri, il passaggio più frequente di qualsiasi array per puntatore anziché per valore consente di utilizzare un registro come ottimizzazione delle chiamate di subroutine.


2
Ho alcune schede che hanno 256 byte di RAM per i dati e 2K EEPROM per il codice. Non vuoi fare una copia di un array lì.
Jerry Jeremiah,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.