Partage
  • Partager sur Facebook
  • Partager sur Twitter

Adresses et tableau, prend les mauvaises valeurs..

Tableaux

    4 janvier 2022 à 21:10:52

    Quel que soit le compilateur, le paramètre a est du type int*, tous respectent la norme. Ce qui les distingue ne va jouer que sur les avertissements qui seront générés avec une aide supplémentaire de gcc qui va signaler que le paramètre passé n'est pas un simple pointeur, mais c'est hors norme.
    • Partager sur Facebook
    • Partager sur Twitter

    En recherche d'emploi.

      4 janvier 2022 à 21:31:35

      En fait non, la norme précise que le type d'un paramètre de type tableau de T est ajusté en pointeur sur T. Mais dans le scope de la signature le paramètre reste de type tableau de T. Cela se remarque dans le cas où le type T est incomplet ;

      Par exemple avec le code :

      struct foo;
      
      struct foo *bar(struct foo array[]);
      
      struct foo *bar(struct foo array[])
      {
      	return array;
      }
      


      gcc et clang vont émettre une erreur :

      $ gcc -c arr.c
      arr.c:3:28: error: array type has incomplete element type ‘struct foo’
          3 | struct foo *bar(struct foo array[]);
            |                            ^~~~~
      arr.c:5:28: error: array type has incomplete element type ‘struct foo’
          5 | struct foo *bar(struct foo array[])
            |                            ^~~~~
      
      $ clang -c arr.c
      arr.c:3:33: error: array has incomplete element type 'struct foo'
      struct foo *bar(struct foo array[]);
                                      ^
      arr.c:1:8: note: forward declaration of 'struct foo'
      struct foo;
             ^
      arr.c:5:33: error: array has incomplete element type 'struct foo'
      struct foo *bar(struct foo array[])
                                      ^
      arr.c:1:8: note: forward declaration of 'struct foo'
      struct foo;
             ^
      2 errors generated.
      

      que ce soit à la définition ou à la déclaration.

      Alors que msvc ou icc compilent le code sans rien dire (le lien dirige vers godbolt pour faire des tests avec différents compilos).

      gcc et clang se réfèrent à la section 6.7.6.2 Array Declarators  où le premier alinéa interdit la déclaration d'un tableau dont le type des éléments est incomplet ; d'où l'erreur, puisqu'on déclare un tel tableau dans la signature de la fonction.

      En revanche, msvc et icc interprètent plus largement les alinéas 4,7 et 12 de  6.7.6.3 Function declarators où cela est permis si on ajuste le type du paramètre avant vérifier si le tableau peut ou non être déclaré … et un paramètre de type pointeur sur T sera toujours complet.

      source : discussion HS avec Markand ⇒ http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf#page=149 

      La norme est ambigüe sur ce point, enfin àmha.

      Edit : liens vers godbolt

      -
      Edité par White Crow 4 janvier 2022 à 21:44:08

      • Partager sur Facebook
      • Partager sur Twitter
        4 janvier 2022 à 23:29:02

        En effet, c'est ambiguë.
        J'étais resté sur le fait que si on est pas dans le cas d'un VLA ou que le mot static n'est pas présent, on devait être compatible avec les versions précédentes du C. D'où une conversion systématique en pointeur.

        Comme je travaille plus en C++ j'ai loupé certaines subtilités du C. D'ailleurs MSVC ne compile pas le C, mais plutôt un C++ réduit d'où le fait qu'il ne signale pas un tableau dans ce cas.

        Hors sujet, la version C++ de l'interprétation des paramètres de fonction:
        9.3.4.6 Functions
        5. The type of a function is determined using the following rules. The type of each parameter (including function parameter packs) is determined from its own parameter-declaration (9.3). After determining the type of each parameter, any parameter of type “array of T” or of function type T is adjusted to be “pointer to T”. After producing the list of parameter types, any top-level cv-qualifiers modifying a parameter type are deleted when forming the function type. The resulting list of transformed parameter types and the presence or absence of the ellipsis or a function parameter pack is the function’s parameter-type-list.

        Et une section qui indique clairement que l'on n'a pas de problème même si le type est incomplet dans ce cas:
        9.3.4.5 Arrays
        7. In addition to declarations in which an incomplete object type is allowed, an array bound may be omitted in some cases in the declaration of a function parameter (9.3.4.6). An array bound may also be omitted when an object (but not a non-static data member) of array type is initialized and the declarator is followed by an initializer (9.4, 11.4, 7.6.1.4, 7.6.2.8). In these cases, the array bound is calculated from the number of initial elements (say, N) supplied (9.4.2), and the type of the array is “array of N U”.
        Mais c'est en effet un hors sujet.

        • Partager sur Facebook
        • Partager sur Twitter

        En recherche d'emploi.

          5 janvier 2022 à 14:25:40

          Personnellement, je trouve l'interprétation gcc/clang plus correcte dans le sens où «il est interdit de déclarer un tableau dont le type des éléments est incomplet» permet de garder la ligne «mis à part avec sizeof et l'opérateur unaire &, une expression de type tableau de T est toujours ajustée en un pointeur sur T pointant sur le premier élément du tableau». Cela me semble dans l'ensemble plus cohérent (et plus simple).
          • Partager sur Facebook
          • Partager sur Twitter
            7 janvier 2022 à 2:39:20

            Est-ce que l'interprétation GCC/clang cause une limitation inutile au langage?
            A priori je pensais que oui.
            Mais en fait, avec un type incomplet, on ne peut pas déréférencer ni ajouter une valeur au pointeur, donc il me semble qu'on ne peut pas l'utiliser comme un pointeur pointant un élément de tableau.

            • Partager sur Facebook
            • Partager sur Twitter
              7 janvier 2022 à 10:10:50

              Marc Mongenet a écrit:

              Est-ce que l'interprétation GCC/clang cause une limitation inutile au langage?
              A priori je pensais que oui.
              Mais en fait, avec un type incomplet, on ne peut pas déréférencer ni ajouter une valeur au pointeur, donc il me semble qu'on ne peut pas l'utiliser comme un pointeur pointant un élément de tableau.


              Ce n'est pas une limitation dans le sens où si on utilise un pointeur sur un type incomplet c'est surtout pour éviter qu'on y accède n'importe comment, c'est une façon d'implémenter l'encapsulation en C.
              Et les pointeurs sur des types incomplets devraient être généralisés dans tout code de bibliothèque (qu'elle soit de convénience ou utilitaire). Cela n'a que des avantages car ça rend le code bien plus lisible, ça évite des couplages forts, le debug et les tests sont facilités, on a une vision claire de l'interface, …

              C'est juste surprenant, car implicitement (naïvement?) je pensais les deux notations complètement équivalentes, alors que dans ce cas non.

              • Partager sur Facebook
              • Partager sur Twitter

              Adresses et tableau, prend les mauvaises valeurs..

              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
              • Editeur
              • Markdown