La fonction suivante "incrémenter" ajoute 1 à un nombre représenté sous forme de tableau.

int*  increment(int array[], int size, int *sizeLen)
{
    int temp[size+1];

    int carry = 0;
    carry = (array[size-1]+1)/10;
    temp[size] = (array[size-1]+1)%10;

    for(int i=size-2;i>=0;i--)
    {
        temp[i+1] = (array[i] + carry)%10;
        carry = (array[i]+carry)/10;
    }
    if(carry)
    {
        temp[0] = 1;
        *sizeLen = size+1;
        return temp;
    }
    else
    {
        *sizeLen = size;
        return (temp+1);
    }
}

int main()
{
    int array[] = {9,9,9};
    int length;
    int *res = increment(array, sizeof(array)/sizeof(int), &length);
    for(int i=0;i<length;i++)
    {
        cout << res[i] << " ";
    }
}

Je sais que gcc prend en charge les tableaux de longueur variable et ils sont stockés sur pile. Je m'attends à ce que la température devienne hors de portée une fois que cette fonction se termine et que la tentative d'impression du tableau dans main devrait imprimer des valeurs de déchets. Mais dans mon cas, les valeurs réelles sont imprimées. Quand le tableau de longueur variable déclaré dans la fonction est-il hors de portée?

0
eagle 24 janv. 2017 à 11:32

4 réponses

Meilleure réponse

La clé ici est en effet la durée de stockage de la baie. Il a une durée de stockage automatique. La durée de vie des variables avec une durée de stockage automatique se termine au moment où la portée dans laquelle elles se trouvent est quittée.

Il fait exactement ce que vous attendez. Mais rien en C ne vous empêche de prendre l'adresse d'un objet local et de la renvoyer depuis la fonction.

L'utilisation de ce pointeur est un comportement indéfini. Cela peut sembler fonctionner, mais le tableau est toujours à toutes fins utiles "mort". Ces pointeurs sont connus familièrement sous le nom de "pointeurs pendants".


Eh bien, ce qui précède est vrai pour C. Comme il s'agit de l'extension GCC, il en va de même pour la plupart, mais il peut être nécessaire de le prendre avec un grain de sel.

1
StoryTeller - Unslander Monica 24 janv. 2017 à 09:18

Cela ne fonctionnera pas. Vous renvoyez un pointeur vers un tableau local, qui sera supprimé (probablement écrasé / réutilisé) dès le retour de la fonction.

La manière C ++ de faire des choses comme ça est d'utiliser std::vector<>. Par exemple (en supposant que dans votre original size et sizelen se réfèrent respectivement au nombre d'éléments dans array et le renvoyé)

std::vector<int> increment(std::vector<int> const&array)
{
    std::vector<int> temp(array.size());
    auto a = array.rbegin();
    auto b = temp.rbegin();
    auto carry = (*a+1)/10;
    *b = (*a+1)%10;
    for(++a,++b; a!=array.rend(); ++a,++b)
    {
        *b = (*a+carry)%10;
        carry = (*a+carry)/10;
    }
    if(carry) { // we must add another element into temp at the start
                // that cannot be done with vector, hence we must create
                // another vector. Note that this should rarely happen.
       std::vector<int> result(temp.size()+1);
       auto r = result.begin();
       *r = 1;
       std::copy(temp.begin(),temp.end(),++r);
       return result;
    } else
       return temp;
}

Notez que votre code serait beaucoup plus simple si vous aviez défini l'ordre des chiffres dans l'autre sens, c'est-à-dire le chiffre le moins significatif comme premier élément (index 0). De plus, comme vos chiffres semblent être décimaux, vous pouvez utiliser un type plus petit que int. Dans ce cas, le code ressemblerait à

std::vector<std::uint8_t> increment(std::vector<std::uint8_t> const&input)
{
    std::vector<std::uint8_t> result;
    result.reserve(input.size()+1);
    auto a = input.begin();
    auto carry = (*a+1)/10;
    result.push_back((*a+1)%10);
    for(++a; a!=input.end(); ++a)
    {
        result.push_back((*a+carry)%10);
        carry = (*a+carry)/10;
    }
    if(carry)
        result.push_back(1);
    return result;
}
1
Walter 24 janv. 2017 à 08:57

Il s'agit d'un comportement indéfini. La prochaine fois qu'un programme sera poussé dans la pile, les données seront perdues.

Ne comptez pas sur cela pour les programmes professionnels.

0
user6754053user6754053 24 janv. 2017 à 08:35

Vous avez raison. temp est hors de portée et devrait afficher des valeurs inutiles.

Mais parfois, il imprime des valeurs correctes. Parce que la mémoire de la pile locale n'est pas effacée / remplacée immédiatement lorsque la fonction actuelle se termine.

0
zhm 24 janv. 2017 à 08:40