Проблема в элементарном парсинге

Всем привет. Делаю эмуляцию ЭВМ. Но в данном случае это неважно, так как проблема возникла при парсинге строки в массив интов. Прикол в том, что если обратится к элементу массива обычно, то все нормально, но если я хочу вывести в консоль через цикл, то выходит ерунда. На функцию "adder" можете не смотреть, но на всякий случай прикрепил. Помогите, пожалуйста.

#include "stdlib.h"

#define BIT 8

int *adder(int *, int *);
int *parse(char *);

int main()
{
    int a[8] = {1, 1, 0, 1, 0, 1, 1, 1};
    int b[8] = {1, 1, 0, 1, 0, 1, 1, 0};

    char bin[] = "11010111";

    int *c;
    c = adder(a, b);
    int i;
    int *qwe = malloc(BIT * sizeof(int));
    qwe = parse(bin);
    for (i = 0; i < BIT; i++)
    {
        printf("%d\n", qwe[i]);
    }

    return 0;
}

int *adder(int *a, int *b)
{
    int i;
    int *c = malloc(BIT * sizeof(int));
    int carry = 0;
    for (i = BIT - 1; i >= 0; i--)
    {
        if (a[i] == 0 && b[i] == 0)
        {
            if (carry == 1)
            {
                c[i] = 1;
                carry--;
            }
            else
            {
                c[i] = 0;
            }
        }
        if ((a[i] == 1 && b[i] == 0) || (a[i] == 0 && b[i] == 1))
        {
            if (carry == 1)
            {
                c[i] = 0;
            }
            else
            {
                c[i] = 1;
            }
        }
        if (a[i] == 1 && b[i] == 1)
        {
            if (carry == 1)
            {
                c[i] = 1;
            }
            else
            {
                c[i] = 0;
                carry++;
            }
        }
    }

    return c;
}

int *parse(char *a)
{
    int i;
    int res[8];
    for (i = 0; i < BIT; i++)
    {
        switch(a[i])
        {
        case '1':
            res[i] = 1;
            break;
        case '0':
            res[i] = 0;
            break;
        default:
            printf("Error");
            exit(1);
        }
    }

    return res;
}

Ответы (1 шт):

Автор решения: V-Mor

Комментаторы @wololo и @avp уже, по сути, ответили на Ваш вопрос, но, дабы он не висел без формального ответа, вынесу сюда их замечания с пояснениями.

Когда Вы в функции int *parse(char *a) создаёте массив вот так:

int res[8];

Вы создаёте локальный массив, который будет существовать до тех пор, пока работает функция. Как только функция завершится, память этого массива будет освобождена и, следовательно, указатель res, который Вы возвращаете в return res;, будет уже невалиден (т.е. указывать на память, в которой нет нужных нам данных).

Лучшим решением здесь будет записать результирующий массив в выделенную ранее с помощью malloc память, т.к. эта память не будет освобождена до тех пор, пока не будет вызван соответствующий realloc, либо работа программы не будет полностью завершена. Чтобы функция записала результат именно в эту память, следует передать в функцию указатель на эту память. То есть Ваш код должен стать примерно таким (не изменённую функцию не включил для экономии места):

#include "stdlib.h"

#define BIT 8

void parse(char *, int *); // void, потому что результат будет помещён в память, на которую указывает второй аргумент, а значит нет нужды его возвращать

int main()
{
    int a[8] = {1, 1, 0, 1, 0, 1, 1, 1};
    int b[8] = {1, 1, 0, 1, 0, 1, 1, 0};

    char bin[] = "11010111";

    int *c;
    c = adder(a, b);
    int i;
    int *qwe = malloc(BIT * sizeof(int));
    parse(bin, qwe); // Передаём выделенную память вторым аргументом
    for (i = 0; i < BIT; i++)
    {
        printf("%d\n", qwe[i]);
    }

    return 0;
}

void parse(char *a, int * res)
{
    int i;
    for (i = 0; i < BIT; i++)
    {
        switch(a[i])
        {
        case '1':
            res[i] = 1; // Теперь res – указатель на массив, выделенный заранее
            break;
        case '0':
            res[i] = 0;
            break;
        default:
            printf("Error");
            exit(1);
        }
    }
}

Также вышеупомянутые комментаторы заметили у Вас ещё одну важную ошибку:

int *qwe = malloc(BIT * sizeof(int)); // Выделяете память, указатель на выделенную память помещается в qwe
qwe = parse(bin); // Тут же помещаете в qwe другой указатель

Помещая в qwe другой указатель, Вы тем самым навсегда теряете указатель на память, выделенную malloc (при перезаписи переменной старое значение уже не восстановить). Выделенная память при этом не очищается и остаётся занятой до конца работы программы, при том, что доступ Вы к ней уже никак не получите. Эта распространённая ошибка называется утечкой памяти и при многократном повторении (например, в цикле) грозит тем, что Ваша программа (не именно эта, любая другая, в которой Вы вдруг повторите эту ошибку) может "есть" много памяти абсолютно бесполезно. Избегайте таких моментов.

→ Ссылка