Le code:
int main(void)
{
auto a=1;
return 0;
}
est compilé sans erreur par le compilateur MS Visual Studio 2012, lorsque le fichier porte l'extension .c. J'ai toujours pensé que, lorsque vous utilisez l'extension .c, la compilation devrait être conforme à la syntaxe C et non à C++. De plus, autant que je sache, auto sans type est autorisé niquement en C++ depuis C++ 11, ce qui signifie que le type est déduit de l’initialiseur.
Cela signifie-t-il que mon compilateur ne s'en tient pas à C ou est-ce que le code est correct en langage C?
auto
est un ancien mot-clé C qui signifie "portée locale". auto a
est le même que auto int a
, et puisque la portée locale est la valeur par défaut pour une variable déclarée dans une fonction, elle est également identique à int a
dans cet exemple.
Ce mot-clé est en réalité un vestige du prédécesseur C, où il n'y avait pas de types de base: tout était int
, pointeur sur int
, tableau de int
. (*) Déclarations être soit auto
ou extrn
[sic]. C a hérité du "tout est int
" comme règle par défaut, vous pouvez donc déclarer des entiers avec
auto a;
extern b;
static c;
ISO C s'en est débarrassé, mais de nombreux compilateurs l'acceptent toujours pour des raisons de compatibilité ascendante. Si cela vous semble peu familier, sachez qu’une règle connexe est à l’œuvre dans
unsigned d; // actually unsigned int
ce qui est encore courant dans le code moderne.
C++ 11 a réutilisé le mot-clé, que peu de programmeurs C++, voire aucun, utilisaient avec la signification originale, pour son inférence de type. Ceci est généralement sans danger car la règle "Tout est int
" de C avait déjà été supprimée en C++ 98; la seule chose qui casse est auto T a
, que personne n'utilisait de toute façon. (Quelque part dans son articles sur l'histoire de la langue , Stroustrup commente à ce sujet, mais je ne trouve pas la référence exacte pour le moment.)
(*) La manipulation des chaînes en B était intéressante: vous utiliseriez des tableaux de int
et regrouperiez plusieurs caractères dans chaque membre. B était en fait BCPL avec une syntaxe différente.
Ceci est à la fois une réponse et un commentaire étendu à Non, ce n'est plus légal depuis 1999. Aucun compilateur C moderne décent ne le permet.
Oui, auto a=1;
est illégal en C1999 (et aussi en 2011). Le fait que cela soit maintenant illégal ne signifie pas qu'un compilateur C moderne devrait rejeter le code contenant de telles constructions. Je dirais exactement le contraire, qu’un compilateur C moderne décent doit tout de même permettre cela.
C'est exactement ce que font clang et gcc lors de la compilation de l'exemple de code de la question par rapport aux versions 1999 ou 2011 de la norme. Les deux compilateurs émettent un diagnostic puis poursuivent comme si la déclaration répréhensible avait été auto int a=1;
.
À mon avis, c'est ce qu'un compilateur décent devrait faire. En émettant un diagnostic, clang et gcc sont totalement conformes à la norme. La norme ne dit pas qu'un compilateur doit rejeter le code illégal. La norme indique simplement qu'une mise en œuvre conforme doit produire au moins un message de diagnostic si une unité de traduction contient une violation d'une règle de syntaxe ou d'une contrainte (5.1.1.3).
À partir d'un code contenant des constructions illégales, tout compilateur décent tentera de comprendre le code illégal afin que le compilateur puisse trouver la prochaine erreur dans le code. Un compilateur qui s'arrête à la première erreur n'est pas un très bon compilateur. Il y a un moyen de donner un sens à auto a=1
, qui consiste à appliquer la règle "implicit int". Cette règle oblige le compilateur à interpréter auto a=1
Comme si c'était auto int a=1
lorsque le compilateur est utilisé en mode C90 ou K & R.
La plupart des compilateurs refusent généralement le code (rejeter: refuser de générer un fichier objet ou un exécutable) contenant une syntaxe non conforme. C'est un cas où les auteurs du compilateur ont décidé que ne pas compiler n'était pas la meilleure option. La meilleure chose à faire est d'émettre un diagnostic, de corriger le code et de continuer. Il y a juste trop de code hérité parsemé de constructions telles que register a=1;
. Le compilateur devrait pouvoir compiler ce code en mode C99 ou C11 (avec un diagnostic, bien sûr).
auto
a une signification dans C
et C++
avant la norme 2011. Cela signifie qu'une variable a une durée de vie automatique, c'est-à-dire durée de vie déterminée par la portée . Ceci est opposé à, par exemple, static
durée de vie, où une variable dure "pour toujours", quelle que soit la portée. auto
est la durée de vie par défaut et n'est presque jamais explicitement énoncé. C’est pourquoi il était prudent de changer le sens en C++
.
Maintenant, dans C
, avant la norme 99, si vous ne spécifiez pas le type d'une variable, la valeur par défaut est int
.
Donc avec auto a = 1;
vous déclarez (et définissez) une variable int
avec une durée de vie déterminée par la portée.
("durée de vie" s'appelle plus proprement "durée de stockage", mais je pense que c'est peut-être moins clair).
En C et dans les dialectes historiques de C++, auto
est un mot clé qui signifie que a
dispose d'un stockage automatique. Comme il ne peut être appliqué qu'aux variables locales, qui sont automatiques par défaut, personne ne l'utilise; C’est la raison pour laquelle C++ a maintenant réutilisé le mot clé.
Historiquement, C a autorisé les déclarations de variable sans spécificateur de type. le type par défaut est int
. Donc, cette déclaration est équivalente à
int a=1;
Je pense que cela est déconseillé (et peut-être même interdit) en C moderne; mais certains compilateurs populaires utilisent par défaut C90 (ce qui, je pense, le permet) et, ennuyeusement, n'activez les avertissements que si vous les demandez spécifiquement. Compiler avec GCC et spécifier C99 avec -std=c99
, ou activer l’avertissement avec -Wall
ou -Wimplicit-int
, donne un avertissement:
warning: type defaults to ‘int’ in declaration of ‘a’
En C, auto
signifie la même chose que register
en C++ 11: cela signifie qu'une variable a une durée de stockage automatique.
Et en C avant C99 (et le compilateur de Microsoft ne prend pas en charge C99 ou C11, même s’il peut en supporter certaines parties), le type peut être omis dans de nombreux cas, où il sera par défaut à int
.
Il ne prend pas du tout le type de l'initialiseur. Vous venez de choisir un initialiseur compatible.
Une classe de stockage définit la portée (visibilité) et la durée de vie des variables et/ou des fonctions dans un programme C.
Les classes de stockage suivantes peuvent être utilisées dans un programme C
auto
register
static
extern
auto
est la classe de stockage par défaut pour toutes les variables locales.
{
int Count;
auto int Month;
}
L'exemple ci-dessus définit deux variables avec la même classe de stockage. auto ne peut être utilisé qu’à l’intérieur de fonctions, c’est-à-dire de variables locales.
int
est le type par défaut pour auto
dans le code ci-dessous:
auto Month;
/* Equals to */
int Month;
Le code ci-dessous est également légal:
/* Default-int */
main()
{
reurn 0;
}
Le type de compilation Visual Studio est disponible à l'adresse right click on file -> Properties -> C/C++ -> Advanced -> Compile As
. Pour s’assurer qu’il est compilé en C force /TC
option.Ensuite, c’est ce que dit larsmans (ancien mot-clé C auto
). Il pourrait être compilé en C++ à votre insu.