Pourquoi les tableaux ne peuvent-ils pas être passés comme arguments de fonction en C?

12

Suite à ce commentaire , j'ai essayé de google pourquoi, mais mon google-fu a échoué.

Commentaire du lien:

[...] Mais l'important est que les tableaux et les pointeurs sont des choses différentes en C.

En supposant que vous n'utilisez aucune extension de compilateur, vous ne pouvez généralement pas passer un tableau lui-même à une fonction, mais vous pouvez passer un pointeur et indexer un pointeur comme s'il s'agissait d'un tableau.

Vous vous plaignez effectivement que les pointeurs n'ont pas de longueur attachée. Vous devriez vous plaindre du fait que les tableaux ne peuvent pas être passés comme arguments de fonction, ou que les tableaux se dégradent implicitement en pointeurs.

Florian Margaine
la source
Je ne suis pas sûr que ce soit la réponse, mais une partie du type d'un tableau est sa taille, donc je pense que vous devrez définir une fonction pour chaque taille que vous souhaitez accepter.
clcto
Voulez-vous dire en tant que pointeurs de fonction ? Veuillez clarifier la question.
user949300
2
@ user949300 Non, du contexte du commentaire, c'est assez clair; vous ne pouvez pas passer un tableau à une fonction car elle devient un pointeur, et il veut savoir pourquoi c'est le cas.
Doval
@DocBrown rlemon a proposé une modification pour cela.
Florian Margaine

Réponses:

18

Ma première supposition pour la raison était simplement pour des raisons de performances et d'économie de mémoire, ainsi que pour la facilité d'implémentation du compilateur (en particulier pour le type d'ordinateurs à l'époque où C a été inventé). Le passage d'énormes tableaux "par valeur" semblait avoir un impact énorme sur la pile, il a besoin d'une opération de copie de tableau complète pour chaque appel de fonction, et probablement le compilateur doit être plus intelligent pour sortir le code d'assemblage correct (bien que le dernier point soit discutable) . Il serait également plus difficile de traiter les tableaux alloués dynamiquement de la même manière que les tableaux alloués statiquement (du point de vue de la syntaxe du langage).

EDIT: après avoir lu certaines parties de ce lien , je pense que la vraie raison (et la raison pour laquelle les tableaux dans struct sont traités comme des types de valeur, alors que seuls les tableaux ne sont pas) est la rétrocompatibilité prédécesseur C B . Voici la citation de Dennis Ritchie:

[...} La solution a constitué le saut crucial dans la chaîne évolutive entre BCPL sans type et C. typé. Elle a éliminé la matérialisation du pointeur dans le stockage, et a plutôt provoqué la création du pointeur lorsque le nom du tableau est mentionné dans une expression. La règle, qui persiste dans le C d'aujourd'hui, est que les valeurs de type tableau sont converties, lorsqu'elles apparaissent dans des expressions, en pointeurs vers le premier des objets composant le tableau.

Cette invention a permis à la plupart des codes B existants de continuer à fonctionner, malgré le changement sous-jacent dans la sémantique du langage. [..]

Doc Brown
la source
5
A struct Foo { int array[N]; } peut être passé par valeur. Et le dernier élément concernant le traitement des allocations dynamiques et statiques semble louche (un tableau au sens strict comprend toujours une taille, les concepts unificateurs pour des choses comme l'indexation de tableaux sont des pointeurs couplés à une décomposition de tableau à pointeur), pourriez-vous élaborer?
@delnan: Je pense que les principes généraux énoncés ici sont solides. De toute évidence, si vous enveloppez votre tableau dans une structure, vous spécifiez votre intention. Dans le cas général, vous allez presque toujours passer par référence.
Robert Harvey
Je trouve également le commentaire référencé dans le PO inutilement pédant. De toute évidence, vous passez un pointeur plutôt qu'un tableau par valeur. Ce qui est également vrai, cependant, c'est que vous passez effectivement un tableau par référence. Si l'objection est qu'il n'y a pas de longueur attachée, il est assez facile de passer cela également.
Robert Harvey
@RobertHarvey C'est toujours une asymétrie dans le système de type: tout est passé par valeur, sauf les types de tableau (même si les tableaux qui font partie d'un type struct sont passés par valeur), et il utilise même la même notation exacte (les deux sur le site d'appel et dans la signature de fonction).
@delnan: Pourquoi est-ce pertinent, à part que vous devez vous en souvenir?
Robert Harvey
9

Un mini-ordinateur PDP avec seulement 8 Ko de mémoire ne peut pas allouer une très grande pile. Ainsi, sur une telle machine, il faut être prudent dans la conception (ou l'évolution) d'un langage pour être en mesure de minimiser ce qui doit aller sur la pile pour l'utilisation prévue des appels de sous-programme communs. C est encore utilisé aujourd'hui pour programmer des systèmes embarqués extrêmement limités en mémoire (quelques ko), donc le compromis est généralement bon.

Sur une architecture de processeur qui a très peu de registres, le fait de passer n'importe quel tableau par pointeur plutôt que par valeur permet plus souvent à un registre d'être utilisé comme optimisation d'appel de sous-programme.

hotpaw2
la source
2
J'ai des cartes qui ont 256 octets de RAM pour les données et 2K EEPROM pour le code. Vous ne voulez pas y faire de copie d'un tableau.
Jerry Jeremiah