2010-12-02 4 views
1

Ceci compile dans gcc sans erreurs ou avertissements même avec l'option -Wall ce qui signifie que les limites des tableaux sont vérifiées à l'exécution et que le compilateur ne peut pas détecter l'erreurcomment les tableaux sont traités par gcc [question liée à la programmation C]

#include<stdio.h> 

int main() 
{ 
     int a[2][3][4]; 

     a[1][2][100] = 4 ; 

     return 0; 
} 

Cependant,

#include<stdio.h> 

int main() 
{ 
     int a[2][3]; 

     a[1][2][100] = 4 ; 

     return 0; 
} 

cela génère une erreur lors de la compilation comme:

$ gcc sample.c -Wall 
sample.c: In function ‘main’: 
sample.c:7: error: subscripted value is neither array nor pointer 

Pourquoi est-ce vrai? dans les deux codes, a [1] [2] [100] est invalide. Encore comment le compilateur peut-il détecter ceci est le code2 et pas le code1.

Spécialement lorsque chaque compilateur aplatit tout tableau multidimensionnel en tableaux de dimension unique correspondants, alors comment le compilateur peut-il être sélectivement averti de cette faille dans le code.

Explication ou mention d'un certain livre ou un article où réside l'explication appropriée seront acceptés avec reconnaissance :)

Répondre

4

La différence est le type. C ne vérifie pas les limites mais effectue une vérification de type (statique). Le type de a dans votre premier exemple est int[][][] mais le type dans le second exemple est int[][]. L '"aplatissement" auquel vous faites référence se produit dans la génération de code, qui est (conceptuellement au moins) après vérification de type.

+0

Est-ce parce que int [] [] est réellement int ** et int [] [] [] est int ***? –

+0

@SK 'int *' et 'int []' sont légèrement différents. Former implique une allocation statique (segment de données, etc.) tandis que la dernière implique une allocation dynamique (tas). – chrisaycock

+3

Non. C'est parce que vous pouvez inscrire un int [] avec un int, mais vous ne pouvez pas inscrire un int avec un int. Si vous inscrivez un int [] [] [] avec un int, vous obtenez un int [] []. Si vous inscrivez cela avec un int, vous obtenez un int []. Si vous inscrivez cela avec un int, vous obtenez un int. Si vous inscrivez cela avec un int, vous obtenez une erreur de type. –

4

En premier lieu, les limites du tableau ne sont pas vérifiées lors de l'exécution ou au moment de la compilation. Soyez prudent là-bas. Deuxièmement, votre deuxième cas donne une erreur parce que vous avez une discordance dans la dimension tableau - vous utilisez trois opérateurs d'indice ([]) sur un tableau 2D. Ce n'est pas parce que le tableau est stocké dans la mémoire sous la forme d'un tableau de tableaux qu'il y a un changement de type en cours avec la variable.

L'indexation de tableau est décrite dans la section standard C 6.5.2.1 Indication de tableau.

+0

Si tous les tableaux sont aplatis par le compilateur, comment peut-il distinguer les tableaux 2D et 3D? –

+0

@ S..K, il n'y a pas de cas particulier. Vous pouvez avoir des tableaux de n'importe quel type. Les tableaux "3D" ne sont que des tableaux de tableaux "2D", etc. Toute indexation est basée sur l'arithmétique du pointeur, qui prend en compte la taille de l'objet (qui peut être un tableau). –

+0

Le compilateur doit connaître la forme du tableau. Toutes les dimensions sauf la dernière doivent être déclarées. ex. arr [5] [6] []. C'est nécessaire et suffisant pour interpréter le tableau. – seand

2

Compte tenu

int a[2][3]; 

le compilateur détermine que a[1][2] est de type int. , Accédant à l'élément [100] de c'est donc équivalent à:

int x; 
x[100] = 4; 

Cela vous donne la même erreur sur la valeur indicés.

Questions connexes