0
votes

Affectation de type étrange pour l'index de tableau en C ++

Salut, j'ai un exemple de programme

#include <iostream>

int main() {
    int a = -5;
    int arr[a];
    std::cout << "Size of arr: " << sizeof(arr) << std::endl;
    return 0;
}

Ici, je reçois la sortie de 17179869164.

Ma question est que la valeur de la taille du tableau ne doit pas accepter les valeurs négatives! et si j'essaye de donner un [-5], cela génère une erreur. mais maintenant comment obtenir la sortie de 17179869164.

J'ai aussi mon hypothèse, le -5 est converti en une valeur int non signée de 4294967291 et la taille totale est donnée comme 17179869164 = 4294967291 * 4 (taille of int).

Je voulais donc savoir pourquoi le compilateur transforme le typage de signed int en unsigned int et ne lance pas d'erreur de compilation. J'avais besoin d'une compréhension claire de la façon dont le compilateur exécute ce morceau de code?


4 commentaires

Votre programme est invalide C ++ (peu importe la valeur de A ), car c ++ n'a pas Tableaux de longueur variable .


@Someprogrammerdude merci pour les informations que je ne savais pas. Mais si je l'exécute, il a un programme C complet avec des modifications, j'obtiens une taille de -20% dans gcc, mais ne devrait-il pas le donner comme une erreur de compilation pour avoir fourni une valeur négative?


Quel compilateur utilisez-vous? Visual Studio 2019 génère des erreurs de compilation pour le tableau de longueur variable (comme indiqué par @Someprogrammerdude) et, une fois que vous corrigez cela, pour a étant négatif.


@Frodyne J'utilise le code Visual Studio avec le compilateur g ++ et gcc.


3 Réponses :


2
votes

C'est ce qu'on appelle un comportement indéfini. Pour attraper ce genre de bogue, vous pouvez utiliser l'aide d'un analyseur statique.

Quelqu'un d'autre a demandé quelque chose de similaire ici: Déclaration d'un tableau de longueur négative


0 commentaires

1
votes

Pour C ++, les tableaux de longueur variable ne sont pas fournis par le standard, mais peuvent être fournis par l'extension du compilateur. Pour C, la réponse courte est que la norme convertit la valeur en une valeur entière positive à moins qu'il ne s'agisse d'une expression constante - dans votre cas, ce qui entraîne l'utilisation de la valeur non signée (utilisation de la valeur de complément des deux comme valeur positive). Plus précisément:

C11 Standard - 6.7.6.2 Array déclarateurs (p5)

Si la taille est une expression qui n'est pas une constante entière expression: si elle apparaît dans une déclaration à la portée du prototype de fonction, il est traité comme s'il était remplacé par *; sinon, chaque fois que c'est évalué, il doit avoir une valeur supérieure à zéro.


0 commentaires

0
votes

J'ai remarqué un comportement intéressant dans GodBolt .

Je vous ai pris du code et ajouté une deuxième copie où a est déclaré constant:

#include <iostream>

int foo() {
    int a = -5;
    int arr[a];
    std::cout << "Size of arr: " << sizeof(arr) << std::endl;
    return 0;
}

int bar() {
    const int a = -5;
    int arr[a];
    std::cout << "Size of arr: " << sizeof(arr) << std::endl;
    return 0;
}

Ensuite, je leur ai jeté GCC, Clang et MSVC.

Pour autant que je sache, GCC et Clang supportent tous les deux les tableaux de longueur variable (VLA) en tant que " fonctionnalité supplémentaire ", et ils ont tous les deux mangé foo sans une seule plainte. Alors que MSVC, qui ne prend pas en charge les VLA, s'est plaint.

D'un autre côté, aucun d'entre eux n'a accepté bar parce que a était négatif.

Quant à savoir pourquoi GCC et Clang ne peuvent pas dire que a est négatif dans foo , je vais laisser une question pour les personnes plus versées dans le compilateur courage que moi.


0 commentaires