2014 dxdy logo

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

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




Начать новую тему Ответить на тему На страницу Пред.  1, 2, 3  След.
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:17 
Заслуженный участник


18/09/21
1756
Vladimir-80 в сообщении #1536674 писал(а):
Но в данном случае, на мой взгляд, проще и эффективней выделить память сразу под весь результат
Если все строки одной длины, то 'char **' вообще не нужен.
Выделяйте один буфер 'char *', записываейте туда строки по индексированным адресам. Потом просто освобождайте буфер.

-- 28.10.2021, 13:19 --

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

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

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:24 
Заблокирован


19/02/13

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


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

-- 28.10.2021, 13:26 --

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


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

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:30 
Заслуженный участник


18/09/21
1756
Например если у вас 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 
Заблокирован


19/02/13

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

-- 28.10.2021, 13:46 --

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


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

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:47 
Заслуженный участник
Аватара пользователя


16/07/14
9152
Цюрих
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 
Заблокирован


19/02/13

2388
Попробую создать массив не просто символов, а нуль-терминированных строк. Посмотрю, что изменится.

-- 28.10.2021, 13:54 --

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


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

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 14:03 
Заслуженный участник
Аватара пользователя


16/07/14
9152
Цюрих
Vladimir-80 в сообщении #1536690 писал(а):
Функция free(r) смотрит, что адрес $12345$ действительно занят, и освобождает его
Так вы же вызываете free(&p);, а не free(r);.

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 15:05 
Заслуженный участник


18/09/21
1756
zykov в сообщении #1536683 писал(а):
should return an array of c-strings
Это значит "массив нуль-терминированных строк"

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 16:54 
Заблокирован


19/02/13

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

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 17:30 
Заслуженный участник


31/12/05
1517
Vladimir-80 в сообщении #1536740 писал(а):
Вместо const char* r; появилась const char** r;, так как теперь передаю указатель на массив указателей, и возврат соответственно изменился на return r;.
А потом эта r как-то используется? Если нет, можно спокойно выкинуть.

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 17:42 
Заблокирован


19/02/13

2388
Да, так тоже работает. Только пришлось возвращаемый char** res2 привести к (const char**)res2, чтобы компилятор не ругался на несоответствие типа.

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 20:05 
Аватара пользователя


28/10/21
100
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 
Заслуженный участник


31/12/05
1517
Vladimir-80 в сообщении #1536747 писал(а):
Да, так тоже работает. Только пришлось возвращаемый char** res2 привести к (const char**)res2, чтобы компилятор не ругался на несоответствие типа.
То есть глобальные переменные в правильном решении все-таки не используются.

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

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


19/02/13

2388
Почему жульничество? На глобальные переменные в задаче запрета нет.

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение29.10.2021, 01:03 


10/04/12
705
Vladimir-80 в сообщении #1536643 писал(а):
На локальной машине всё работает, на codewars вылетает с ошибкой "SIGSEGV (11). Invalid memory access." - без подробностей.


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

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 36 ]  На страницу Пред.  1, 2, 3  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group