usage - Pointeur vers un tableau de taille non spécifiée "(* p)[]" illégal en C++ mais légal en C



c++ member function pointer (2)

C ++ n'a pas la notion de "type compatible" de C. En C, il s'agit d'une redéclaration parfaitement valide d'une variable:

extern int (*a)[];
extern int (*a)[3];

En C, il s'agit d'une redéclaration parfaitement valide de la même fonction:

extern void f();
extern void f(int);

En C, ceci est spécifique à l'implémentation, mais généralement une redéclaration valide de la même variable:

enum E { A, B, C };
extern enum E a;
extern unsigned int a;

C ++ n'en a pas. En C ++, les types sont soit identiques, soit différents, et s'ils sont différents, la différence est minime.

De même,

int main() {
  const char array[] = "Hello";
  const char (*pointer)[] = &array;
}

est valide en C, mais invalide en C ++: array , malgré le [] , est déclaré comme un tableau de longueur 6. Le pointer est déclaré comme un pointeur sur un tableau de longueur non spécifiée, qui est un type différent. Il n'y a pas de conversion implicite de const char (*)[6] en const char (*)[] .

De ce fait, les fonctions prenant des pointeurs sur des tableaux de longueur non spécifiée sont à peu près inutiles en C ++ et presque certainement une erreur de la part du programmeur. Si vous commencez à partir d'une instance de tableau concret, vous avez presque toujours la taille, de sorte que vous ne pouvez pas prendre son adresse pour la transmettre à votre fonction, car vous auriez une incompatibilité de type.

Et vous n'avez pas besoin non plus de pointeurs vers des tableaux de longueur non spécifiée: la manière normale d'écrire cela dans C, qui se trouve être également valide en C ++, est

int accumulate(int n, int *array)
{
    int i;
    int sum = 0;
    for (i = 0; i < n; ++i) {
        sum += array[i];
    }
    return sum;
}

être appelé comme accumulate(ARRAY_LENGTH(a), a) .

Je viens de découvrir que cela est illégal en C ++ (mais légal en C):

#include <stdio.h>
#include <stdlib.h>
#define ARRAY_LENGTH(A) (sizeof(A) / sizeof(A[0]))

int accumulate(int n, const int (*array)[])
{
    int i;
    int sum = 0;
    for (i = 0; i < n; ++i) {
        sum += (*array)[i];
    }
    return sum;
}

int main(void)
{
    int a[] = {3, 4, 2, 4, 6, 1, -40, 23, 35};
    printf("%d\n", accumulate(ARRAY_LENGTH(a), &a));
    return 0;
}

Il compile sans problème en utilisant gcc -std=c89 -pedantic mais ne compile pas en utilisant g++ . Lorsque j'essaie de le compiler en utilisant g++ je reçois ces messages d'erreur:

main.cpp:5:37: error: parameter 'array' includes pointer to array of unknown bound 'int []'
 int accumulate(int n, int (*array)[])
                                     ^
main.cpp: In function 'int main()':
main.cpp:18:50: error: cannot convert 'int (*)[9]' to 'int (*)[]' for argument '2' to 'int accumulate(int, int (*)[])'
     printf("%d\n", accumulate(ARRAY_LENGTH(a), &a));

Je l'utilise depuis longtemps dans mon code C et je ne savais pas que c'était illégal en C ++. Pour moi, cela semble être un moyen utile de documenter qu'une fonction prend un tableau dont la taille n'est pas connue auparavant.

Je veux savoir pourquoi c'est C légal mais invalide C ++. Je me demande aussi ce que cela a fait que le comité C ++ a décidé de le retirer (et de briser cette compatibilité avec C).

Alors, pourquoi ce code C légal est-il un code C ++ illégal?


Dan Saks a écrit à ce sujet en 1995 , lors de la préparation de la normalisation C ++:

Les comités ont décidé que des fonctions comme celle-ci, qui acceptent un pointeur ou une référence à un tableau avec une limite inconnue, compliquent les règles de correspondance et de résolution de surcharge des déclarations en C ++. Les comités ont convenu que, puisque ces fonctions sont peu utiles et assez rares, il serait plus simple de les interdire. Par conséquent, le brouillon C ++ indique maintenant:

Si le type d'un paramètre inclut un type de pointeur de forme vers un tableau de limite inconnue de T ou une référence à un tableau de limite inconnue de T, le programme est mal formé.





pointers