Переменные стекового массива не соответствуют C - PullRequest
0 голосов
/ 04 февраля 2019

Следующая программа выдает странное поведение: makefile

all:
    gcc main.c -o main;

пример сборки

./main 3 5 6 9

main.c

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(int argc, char **argv) {
    if (argc < 1) {
            fprintf(stderr, "insertion(): requires a list of numbers\n");
            exit(1);
    } else if (argc - 1 > INT_MAX) {
            fprintf(stderr, "insertion(): requires a list of numbers less than INT_MAX\n");
            exit(1);
    }
    int ints[argc - 1];
    for (int i = 1; i < argc; i++) {
            char ci = *argv[i];
            int i = ci - '0';
            ints[i - 1] = i;
            printf("%d\n", ints[i - 1]);
    }
    for (int j = 0; j < argc - 1; j++) {
            printf("%d\n", ints[j]);
    }
    return 0;
}

производит:

3
5
6
9
random stack stuff
random stack stuff
random stack stuff
random stack stuff

Должна ли быть концепция, которую я здесь упускаю?Изменить: Рабочее решение спасибо @ tilz0R, @ dbush

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(int argc, char **argv) {
    if (argc < 1) {
            fprintf(stderr, "insertion(): requires a list of numbers\n");
            exit(1);
    } else if (argc - 1 > INT_MAX) {
            fprintf(stderr, "insertion(): requires a list of numbers less than INT_MAX\n");
            exit(1);
    }
    int ints[argc - 1];
    int k;
    for (int i = 1; i < argc; i++) {
            char ci = *argv[i];
            k = ci - '0';
            ints[i - 1] = k;
            printf("%d\n", ints[i - 1]);
    }
    for (int j = 0; j < argc - 1; j++) {
            printf("%d\n", ints[j]);
    }
    return 0;
}

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

Посмотрите внимательно на этот цикл:

for (int i = 1; i < argc; i++) {
        char ci = *argv[i];
        int i = ci - '0';
        ints[i - 1] = i;
        printf("%d\n", ints[i - 1]);
}

Вы определяете i как свою переменную управления цикла.Но затем вы определяете другую переменную с именем i внутри цикла.Это затеняет i, определенный в начале цикла.

Глядя на эти строки:

int i = ci - '0';
ints[i - 1] = i;

На первой итерации цикла вы читаете значение '3'.Это хранится в новом i.Тогда вторая строка становится такой:

ints[3 - 1] = 3;

Более поздние эффективные итерации делают это:

ints[5 - 1] = 5;
ints[6 - 1] = 6;
ints[9 - 1] = 9;

Таким образом, вы никогда не пишете в первые два элемента массива и пишете после концамассив 3 раза.Запись после конца массива, а также чтение неинициализированных элементов вызывает неопределенное поведение .

Дайте внутреннему i другое имя (например, value).Это предотвращает маскирование внешнего i.

for (int i = 1; i < argc; i++) {
        char ci = *argv[i];
        int value = ci - '0';
        ints[i - 1] = value;
        printf("%d\n", ints[i - 1]);
}
0 голосов
/ 04 февраля 2019

У вас есть int i; внутри первого for дважды в другой области видимости.

for (int i = 1; i < argc; i++) {
    char ci = *argv[i];
    int i = ci - '0'; // <--- this is problematic
    ints[i - 1] = i;  // <--- this is problematic 
    printf("%d\n", ints[i - 1]);
}

Лучше было бы

for (int i = 1; i < argc; i++) {
    char ci = *argv[i];
    int tmp = ci - '0';
    ints[i - 1] = tmp;
    printf("%d\n", ints[i - 1]);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...