#c #pointers
#c #указатели
Вопрос:
Я хочу передать указатель на указатель на функцию, выделить память в функции, заполнить ее строками и получить ее обратно, но, похоже, все не работает. Программа ничего не выводит за пределы функции. Это наиболее важные фрагменты кода:
struct record ** getRegEx( int *counter, char** keys )
{
*counter = 0;
//get some records, its number is *counter, max lenght of each string is 64
//COUNTER IS NOT 0! ITS VALUE DEPENDS ON OTHER OPERATIONS I HAVENT WRTTEN HERE
//...
keys =(char ** ) malloc((*counter)*(sizeof(char *)));
for (j = 0; j < *counter; j )
{
keys[j] = (char* )malloc(64*sizeof(char));
}
strcpy(keys[j],key.dptr);
printf("size %d : n", sizeof(**keys));//1
printf("size %d : n", sizeof(*keys));//4
printf("size %d : n", sizeof(keys[0]));//4
printf("size %d : n", sizeof(keys));//4
//...
}
/*Out of the function, inside the function OK*/
char** keys;
int count;
results = getRegEx(amp;count, amp;keys); //amp;keys or keys - makes no difference
for(int k=0 ; k< *count;k ) //test
{
printf("keys in db %s: sn", keys[k]); //nothing!?
}
Я заставил это работать, заменив заголовок функции чем-то вроде struct record ** getRegEx( int *counter, char*** keys )
(и используя *keys и *keys [i] вместо key и keys [i] внутри функции). Спасибо за все!
Ответ №1:
Вы передаете ноль в malloc
, поэтому вам нечего возвращать keys
.
Ваш for
цикл никогда не выполняется.
Оба потому, что (*counter)
равно нулю.
Комментарии:
1. Нет, он передает мусор в
malloc
.2. Ну, он установил *counter равным нулю, а затем передал ((*counter)*(sizeof(char *))) в malloc, то есть 0.
3. значение счетчика не равно 0, это просто инициализация. В моей программе есть еще немного кода.
Ответ №2:
-
Здесь серьезная проблема:
results = getRegEx(amp;count, amp;keys); //amp;keys or keys - makes no difference
Ваш комментарий неверен — это действительно имеет значение.
keys
имеет типchar **
(которыйgetRegEx
ожидает),amp;keys
имеет типchar ***
. -
Ваша функция имеет возвращаемый тип, но ничего не возвращает.
-
Вы выделяете динамическую память для вашей
keys
переменной в функции, но функция (в том виде, в каком она написана) не может передать эту память из функции. Ваша функция должна приниматьchar ***
, и вы должны передать ее какamp;keys
(которая, как было указано ранее, имеет типchar ***
.) -
Ваш размер всегда будет равен нулю, поскольку вы устанавливаете
*count = 0
в начале своей функции (когда вы вообще не должны устанавливать его в своей функции и должны передаватьcount
по значению, а не по указателю). Точные эффектыmalloc(0)
определяются реализацией. -
Вы приводите возвращаемое значение
malloc
. Это не так, но в C в этом нет необходимости (и если вы действительно используете C , вам следует так и сказать) и может усложнить задачу в будущем. -
Вы никогда не проверяете возвращаемые значения
malloc
на предмет сбоя. -
Вы используете
counter
указатель вне функции, в которой он объявлен. Вне вызова функции вы должны использоватьcount
переменную, которую вы передали в качестве параметра. Параметры функции не продолжают существовать вне функций, в которых они используются.
Ответ №3:
Основные проблемы:
-
Ваши типы не совпадают. При вызове
getRegEx(amp;count, amp;keys)
тип выраженияamp;keys
являетсяchar ***
, а неchar **
. Обратите внимание, что если вы хотите изменить значениеkeys
, вам придется передать указатель на него. Это приводит к следующей проблеме… -
Поскольку вы изменяете значение параметра
keys
, а не то, на что он указывает, любые изменения, которые вы вносите в функцию, не отражаются в вызывающем объекте.
Вот измененная версия вашего кода, иллюстрирующая то, что, я думаю, вы пытаетесь сделать:
struct record **getRegEx(int *counter, char ***keys)
{
...
// type of keys = char ***
// type of *keys = char **
// type of **keys = char *
*keys = malloc(*counter * sizeof **keys); // note no cast, operand of sizeof
if (*keys)
{
int j;
for (j = 0; j < *counter; j )
{
// type of (*keys)[j] == char *
// type of *(*keys)[j] = char
(*keys)[j] = malloc(64 * sizeof *(*keys)[j]);
}
}
...
}
Обратите внимание, что я не приводил результат malloc
. Начиная с версии стандарта C 1989 года, вам не нужно этого делать, так что это избавляет от визуального беспорядка. Это также защищает вас от потенциальной ошибки; если вы забудете включить stdlib.h
или иным образом не будете создавать прототип для malloc
в области видимости, компилятор предположит, что функция возвращает int
. Без приведения вы получите диагностику порядка «несовместимые типы для назначения». Добавление приведения приведет к подавлению диагностики, и в результате у вас могут возникнуть незначительные (или не очень заметные) ошибки во время выполнения.
Также обратите внимание, что я использую sizeof
для объектов, а не типов. Опять же, это помогает уменьшить визуальный беспорядок, а также защищает вас в случае, если вы решите изменить базовый тип keys
; вам также не нужно обновлять каждый malloc
вызов.
Почему (*keys)[j]
вместо *keys[j]
? Выражение keys
не является местоположением начала нашего массива, а скорее указывает на это местоположение. Мы должны разыменовать keys
, чтобы получить адрес массива, который мы затем индексируем.
Ответ №4:
У вас есть функция getRegEx
, которая объявлена для возврата struct record **
.
Вы знаете, чего не хватает в этой функции?
все, что выглядит как return
оператор!