2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




На страницу Пред.  1, 2, 3  След.
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:17 
Vladimir-80 в сообщении #1536674 писал(а):
Но в данном случае, на мой взгляд, проще и эффективней выделить память сразу под весь результат
Если все строки одной длины, то 'char **' вообще не нужен.
Выделяйте один буфер 'char *', записываейте туда строки по индексированным адресам. Потом просто освобождайте буфер.

-- 28.10.2021, 13:19 --

Vladimir-80 в сообщении #1536677 писал(а):
Вопрос хороший, но так поставлена задача

Так там был 'const char **', т.е. указатель не должен менятся, что правильно.
А если у вас один буфер 'char *', то он должен быть без 'const', т.к. вы туда писать будете.

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:24 
zykov в сообщении #1536679 писал(а):
Выделяйте один буфер 'char *', записываейте туда строки по индексированным адресам. Потом просто освобождайте буфер.


Можете пояснить?
Моя задача - создать варианты последовательности цифр и передать их вызывающей функции. Я для этого использую массив в куче. Освобождать эту память будет уже вызывающая функция.

-- 28.10.2021, 13:26 --

zykov в сообщении #1536679 писал(а):
А если у вас один бувер 'char *', то он должен быть без 'const', т.к. вы туда писать будете.


У меня так и сделано.

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:30 
Например если у вас 10 строк длины 5 (указатели на которые лежати в массиве names[]), то
Используется синтаксис C++
    char *res = malloc(10*6*sizeof(char));
    for(int i=0; i<10; i++)
        strcpy(res+i*6, names[i]);
 


-- 28.10.2021, 13:32 --

Vladimir-80 в сообщении #1536653 писал(а):
Таковы условия задачи
код: [ скачать ] [ спрятать ]
Используется синтаксис C
#include <stdlib.h>

//Function should return an array of c-strings with all possible PINs.
//It must allocate all required meomry, but there are no requirements
//as to how it should be done. It must be possible to free
//allocated memory with a call to free_pins.
//Upon return, count should contain the amount of returned PINs.
const char** get_pins(const char* observed, size_t* count) {
*count = 1;
return NULL;
}

//This function will be called once per every call to get_pins
//with a pointer value returned by such call.
void free_pins(const char ** pins) {
//...do your cleanup, if necessary
}
 
Если надо сделать именно по этой спецификации, то не забивайте голову одним буфером.
Делайте массив строк, выделяйте каждую строку персонально, потом освобождайте каждую строку персонально.

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:41 
Задача не про нуль-терминированные строки, она про комбинаторику. Дан пин-код, каждая цифра которого может быть заменена на определённый набор соседних с нею. Надо перечислить все возможные варианты. И да, место в выходной массив на завершающие нули я добавлял - не помогло.

-- 28.10.2021, 13:46 --

mihaild в сообщении #1536651 писал(а):
у вас зовется free с адресом переменной на стеке


А как вызвать free() правильно?

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:47 
Аватара пользователя
Vladimir-80, вам нужно получить массив строк char** pins;, такой что pins[0], pins[1], ... - c-строки с пинами. Для этого нужно, очевидно, выделить память под сам массив pins, выделить память под строки и записать адреса строк в этот массив (ну и еще строки нужным образом заполнить). Выделить память под строки можно как одним куском, так и отдельно под каждую. При большом желании можно даже выделить сразу память и под строки, и под массив, но от необходимости заполнить массив это вас не избавит.

-- 28.10.2021, 13:49 --

Vladimir-80 в сообщении #1536686 писал(а):
А как вызвать free() правильно?
free можно вызывать только на указатели, которые вернула malloc (на самом деле не совсем, но это достаточно хорошее приближение). Но в любом случае это не поможет, потому что у вас не то создается что просили.

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:50 
Попробую создать массив не просто символов, а нуль-терминированных строк. Посмотрю, что изменится.

-- 28.10.2021, 13:54 --

mihaild в сообщении #1536689 писал(а):
free можно вызывать только на указатели, которые вернула malloc


Malloc взяла кусок памяти, начинающийся с адреса $12345$. Имя массива теперь содержит этот адрес. Я приравниваю указатель $r$ к имени массива - теперь этот указатель тоже содержит $12345$ и указывает на ту область памяти, в которой лежит массив. Функция free(r) смотрит, что адрес $12345$ действительно занят, и освобождает его. Вроде бы всё нормально.

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 14:03 
Аватара пользователя
Vladimir-80 в сообщении #1536690 писал(а):
Функция free(r) смотрит, что адрес $12345$ действительно занят, и освобождает его
Так вы же вызываете free(&p);, а не free(r);.

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 15:05 
zykov в сообщении #1536683 писал(а):
should return an array of c-strings
Это значит "массив нуль-терминированных строк"

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 16:54 
Переформатировал вывод под массив указателей на строки и всё заработало.
Схема возврата указателя на массив с результатом почти не изменилась, работает так же через глобальную переменную. Вместо const char* r; появилась const char** r;, так как теперь передаю указатель на массив указателей, и возврат соответственно изменился на return r;.
Спасибо всем за конструктивное обсуждение, вы мне очень помогли, навели на правильные мысли!

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 17:30 
Vladimir-80 в сообщении #1536740 писал(а):
Вместо const char* r; появилась const char** r;, так как теперь передаю указатель на массив указателей, и возврат соответственно изменился на return r;.
А потом эта r как-то используется? Если нет, можно спокойно выкинуть.

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 17:42 
Да, так тоже работает. Только пришлось возвращаемый char** res2 привести к (const char**)res2, чтобы компилятор не ругался на несоответствие типа.

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 20:05 
Аватара пользователя
Vladimir-80 в сообщении #1536686 писал(а):
А как вызвать free() правильно?


Как вам написали практически с самого начала, если закрыть глаза на отсутствие необходимых стандартных заголовков и объявлений некоторых переменных, немедленная формальная ошибка в вашем коде только одна: при освобождении памяти в `free_pins` вместо `free(p)` должно быть написано `free(*p)`.

За этой ошибкой, однако, скрывается другая формальная ошибка: параметр стандартной функции `free` имеет тип `void *`, а значение `*p` имеет тип `const char *`. В языке С не допускается неявное преобразование `const char *` к `void *`. Для исправления этой ошибки вам придется выполнить приведение явно `free((void *) *p)`.

Других формальных ошибок в приведенном коде нет.

Разумеется, как всегда, приведенные варианты исправления ошибок не являются однозначными. Никто не знает, нужен ли вам вообще этот `const` и почему вы передаете именно двойной указатель в `free_pins`.

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 22:00 
Vladimir-80 в сообщении #1536747 писал(а):
Да, так тоже работает. Только пришлось возвращаемый char** res2 привести к (const char**)res2, чтобы компилятор не ругался на несоответствие типа.
То есть глобальные переменные в правильном решении все-таки не используются.

Просто если у них есть простой тест, в котором сначала два раза вызывается get_pins, а потом два раза free_pins, то жульничество с глобальными переменными сразу вскроется.

 
 
 
 Re: Си передача указателя между функциями
Сообщение29.10.2021, 00:10 
Почему жульничество? На глобальные переменные в задаче запрета нет.

 
 
 
 Re: Си передача указателя между функциями
Сообщение29.10.2021, 01:03 
Vladimir-80 в сообщении #1536643 писал(а):
На локальной машине всё работает, на codewars вылетает с ошибкой "SIGSEGV (11). Invalid memory access." - без подробностей.


Запускать надо с санитайзерами или под valrgind, тогда бо́льшая часть ошибок отловится.

 
 
 [ Сообщений: 36 ]  На страницу Пред.  1, 2, 3  След.


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group