Проблема в элементарном парсинге
Всем привет. Делаю эмуляцию ЭВМ. Но в данном случае это неважно, так как проблема возникла при парсинге строки в массив интов. Прикол в том, что если обратится к элементу массива обычно, то все нормально, но если я хочу вывести в консоль через цикл, то выходит ерунда. На функцию "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 шт):
Комментаторы @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 (при перезаписи переменной старое значение уже не восстановить). Выделенная память при этом не очищается и остаётся занятой до конца работы программы, при том, что доступ Вы к ней уже никак не получите. Эта распространённая ошибка называется утечкой памяти и при многократном повторении (например, в цикле) грозит тем, что Ваша программа (не именно эта, любая другая, в которой Вы вдруг повторите эту ошибку) может "есть" много памяти абсолютно бесполезно. Избегайте таких моментов.