44 votes

Déclarations/définitions en tant que déclarations dans C et C

J'étais confus, quand ce ne serait pas compiler en C:

int main()
{
    for (int i = 0; i < 4; ++i)
        int a = 5; // A dependent statement may not be declaration

    return 0;
}

Je suis habitué à C++ où cela va compiler. J'ai juste regardé stupéfait pendant un moment jusqu'à ce que je me suis souvenu de réponse ici sur DONC comment en C et C++ différentes choses sont considérées comme des "états". C'était à l'égard d'une instruction switch. Une "déclaration" après la boucle for les supports doivent être présents à la fois en C et C++. Cela peut être fait en ajoutant un point-virgule ou la création d'un { } enchevêtrées support de bloc.

En C++ "int a = 7;" est considérée comme une déclaration, définition et initialisation. En C je crois qu'il est également considéré comme l'ensemble de ceux-ci, cependant, en C, il n'est pas considéré comme une "déclaration".

Quelqu'un pourrait-il exactement expliquer pourquoi en C, ce n'est pas une déclaration alors qu'en C++ il est? Ceci est source de confusion mon concept de ce qu'est un énoncé n'est pas parce que l'on dit la langue, il est, et un autre dit que ce n'est pas le cas, donc je suis un peu confus.

17voto

AndyG Points 3298

C++ admis que le "substatement" d'une itération déclaration a été implicitement une instruction composée ([stmt.iter])

Si le substatement dans une itération-déclaration est une déclaration unique et non pas un composé de déclaration, c'est comme si il a été réécrit pour être un composé-déclaration contenant l'original de la déclaration. Exemple:

while (--x >= 0)
   int i;

peut être réécrit de manière équivalente comme

while (--x >= 0) {
   int i;
}

le C standard ne dispose pas de cette langue.

En outre, la définition d'une déclaration changé en C++ pour inclure une déclaration, de sorte que même si le changement ci-dessus n'est pas fait, il serait encore juridique.


La raison que, en ajoutant des accolades fait que cela fonctionne est parce que votre déclaration devient maintenant un composé déclaration qui peuvent inclure des déclarations.

Vous êtes autorisé à faire un identificateur dans un corps de boucle sans accolades, de sorte que vous pouvez faire ceci à la place:

int a = 5;
for (int i = 0; i < 4; ++i)
    a;

16voto

user2079303 Points 4916

En C++, une déclaration est (C++17 projet de norme)

excerpt from [gram.stmt]

statement:
    labeled-statement
    attribute-specifier-seqopt expression-statement
    attribute-specifier-seqopt compound-statement
    attribute-specifier-seqopt selection-statement
    attribute-specifier-seqopt iteration-statement
    attribute-specifier-seqopt jump-statement
    declaration-statement
    attribute-specifier-seqopt try-block

init-statement:
    expression-statement
    simple-declaration

declaration-statement:
    block-declaration

...

Notez qu'il existe des instructions de déclaration en C++, qui sont des déclarations, et sont consolidés. De même, de simples déclarations sont init consolidés. Pas toutes les déclarations sont des énoncés bien. La grammaire de déclarations qu'il contient des choses qui ne sont pas dans la liste des états:

excerpt from [gram.dcl]

declaration:
    block-declaration
    nodeclspec-function-declaration
    function-definition
    template-declaration
    deduction-guide
    explicit-instantiation
    explicit-specialization
    linkage-specification
    namespace-definition
    empty-declaration
    attribute-declaration

block-declaration:
    simple-declaration
    asm-definition
    namespace-alias-definition
    using-declaration
    using-directive
    static_assert-declaration
    alias-declaration
    opaque-enum-declaration

simple-declaration:
    decl-specifier-seq init-declarator-listopt ;
    attribute-specifier-seq decl-specifier-seq init-declarator-list ;
    attribute-specifier-seqopt decl-specifier-seq ref-qualifieropt [ identifier-list ] initializer ;

...

La liste de déclaration des grammaires continue sur quelques pages.


En C, une déclaration est (C11 projet de norme)

excerpt from Statements and blocks

statement:
    labeled-statement
    compound-statement
    expression-statement
    selection-statement
    iteration-statement
    jump-statement

Notez qu'il n'y a pas de déclarations qui sont énoncés dans C.


Ainsi, le sens de l'énoncé est clairement différente dans les langues. Déclaration en C++ semble avoir un sens plus large que la déclaration en C.

9voto

Abhishek Keshri Points 2504

Selon cppreference, C++ comprend les types suivants d' statements:

  1. expression des déclarations;
  2. composé des déclarations;
  3. les instructions de sélection;
  4. itération des déclarations;
  5. sauter des déclarations;
  6. instructions de déclaration;
  7. essayez de blocs;
  8. atomique et la synchronisation des blocs

Alors que C estime types suivants d' statements:

  1. composé états
  2. l'expression des états
  3. les instructions de sélection
  4. itération états
  5. sauter états

Comme vous pouvez le constater, les déclarations ne sont pas considérées statements dans C, alors que ce n'est pas ce cas en C++.

Pour Le C++:

int main()
{                                     // start of a compound statement
    int n = 1;                        // declaration statement
    n = n + 1;                        // expression statement
    std::cout << "n = " << n << '\n'; // expression statement
    return 0;                         // return statement
}                                     // end of compound statement

Pour C:

int main(void)
{                          // start of a compound statement
    int n = 1;             // declaration (not a statement)
    n = n+1;               // expression statement
    printf("n = %d\n", n); // expression statement
    return 0;              // return statement
}                          // end of compound statement

2voto

Vlad from Moscow Points 36219

En C++ déclarations sont consolidés alors que dans C les déclarations ne sont pas consolidés. Donc, d'après le C de la grammaire dans cette boucle for

for (int i = 0; i < 4; ++i)
    int a = 5;

int a = 5; doit être un substatement de la boucle. Cependant c'est une déclaration.

Vous pourriez faire le code à compiler en C en utilisant l'instruction composée, comme par exemple

for (int i = 0; i < 4; ++i)
{
    int a = 5;
}

bien que le compilateur peut émettre un message de diagnostic en disant que la variable a n'est pas utilisé.

Une conséquence de plus que dans C les déclarations ne sont pas consolidés. Vous ne pouvez pas placer une étiquette avant une déclaration en C. Par exemple ce programme

#include <stdio.h>

int main(void) 
{
    int n = 2;

    L1:
    int x = n;

    printf( "x == %d\n", x );

    if ( --n ) goto L1; 

    return 0;
}

ne pas compiler en C si il compile un programme en C++. Toutefois, si à la place de null-déclaration après l'étiquette, alors le programme ne compile.

#include <stdio.h>

int main(void) 
{
    int n = 2;

    L1:;
    int x = n;

    printf( "x == %d\n", x );

    if ( --n ) goto L1; 

    return 0;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X