2010-01-24 5 views
2

Je me tournai vers C++ après une longue période en C#, PHP et d'autres choses et j'ai trouvé quelque chose d'étrange:C++ strcpy expression non-constante sous forme de tableau lié

temp.name = new char[strlen(name) + strlen(r.name) + 1]; 

cette compile

temp.name = (char *)malloc(sizeof(char[strlen(name) 
    + strlen(r.name) + 1])); 

cela ne (temp.name est un char *)

L'erreur du compilateur est

erreur C2540: expression non constante sous forme de tableau lié

Est-ce que quelqu'un sait ce que le problème pourrait être et comment il pourrait y remédier? Je vous remercie.

+0

Si vous utilisez C++, oubliez les tableaux char et utilisez std :: string. –

+0

Alors que le texte du programme semble identique, la sémantique est très différente. Il y a * des types de tableaux en C++ qui ont des tailles de zéro ou des valeurs d'exécution. Mais ces types de tableaux ne sont adressables que par new-type-id. Les spécificateurs de type pour les tableaux déclarés n'utilisent pas de nouveaux ID de type, ils ne sont donc pas en mesure de désigner ces types «fantaisie».Essayez d'écrire 'nouveau (char [strlen (nom)])' ou 'nouveau (char [0]);' et notez comment cela échouera aussi, avec un compilateur conforme: Parce que les parenthèses feront le compilateur former un 'type -id' au lieu d'un 'new-type-id'. Similaire, 'sizeof' s'attend à un' type-id'. –

Répondre

6

sizeof(...) attend une constante expression à la compilation. strlen n'est pas une expression à la compilation, c'est une fonction qui doit être exécutée pour obtenir un résultat. Par conséquent, le compilateur ne peut pas réserver suffisamment de stockage pour un tableau comme celui-ci a déclaré:

char c[strlen("Hello")]; 

Bien que la longueur de la chaîne est clairement 5, le compilateur ne sait pas. Pour éviter ce piège, n'utilisez pas sizeof ici. À la place:

char* c = (char*)malloc(strlen(name)+strlen(rname)+1); 

Ceci vous donne un pointeur sur n octets en retour. sizeof(char)==1 étant toujours vrai, le nombre d'octets dans le tampon est égal au nombre de caractères que vous pouvez y stocker. Pour malloc réseaux de type différent, il faut multiplier la taille statique d'un élément de tableau:

int* c = (int*) malloc(sizeof(int)*100); 

Ceci est Ok, parce que sizeof est appliqué à une expression de la compilation. Bien sûr, la façon C++ est beaucoup plus propre:

int* c = new int[100]; 
0

malloc a besoin d'un size_t son entrée, ce qui signifie que vous devez calculer la taille réelle et passer que au lieu de spécifier le type:

temp.name = (char *) malloc((strlen(name) + strlen(r.name) + 1)) * sizeof(char)); 

Vous devriez probablement utiliser new de toute façon, donc je ne vois pas de vrais problèmes.

+0

1 == sizeof (char) est toujours vrai, donc vous n'avez pas besoin de multiplier par lui. –

+0

Je sais, mais je le fais habituellement au cas où je voudrais changer de type plus tard (au type de caractère large peut-être?). Ensuite, je peux faire quelque chose comme ": s/char/wchar_t/g" dans vim et tout est automatiquement corrigé. :-) –

+0

Si c'est l'intention, alors il est probablement préférable d'utiliser 'sizeof * temp.name' –

1

Le problème est char[...] qui est un type de tableau et dans les tailles de tableau C++ (et C89) doivent être des constantes de compilation. Vous devriez probablement utiliser std :: string au lieu d'allouer la mémoire manuellement par new[] ou malloc(), mais si vous préférez utiliser l'allocation manuelle, calculez la taille directement en tant que nombre de caractères au lieu d'utiliser des tableaux et pour le faire.

Questions connexes