использование указателя на массив символов

#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:

  1. Здесь серьезная проблема:

     results = getRegEx(amp;count, amp;keys); //amp;keys or keys - makes no difference
      

    Ваш комментарий неверен — это действительно имеет значение. keys имеет тип char ** (который getRegEx ожидает), amp;keys имеет тип char *** .

  2. Ваша функция имеет возвращаемый тип, но ничего не возвращает.

  3. Вы выделяете динамическую память для вашей keys переменной в функции, но функция (в том виде, в каком она написана) не может передать эту память из функции. Ваша функция должна принимать char *** , и вы должны передать ее как amp;keys (которая, как было указано ранее, имеет тип char *** .)

  4. Ваш размер всегда будет равен нулю, поскольку вы устанавливаете *count = 0 в начале своей функции (когда вы вообще не должны устанавливать его в своей функции и должны передавать count по значению, а не по указателю). Точные эффекты malloc(0) определяются реализацией.

  5. Вы приводите возвращаемое значение malloc . Это не так, но в C в этом нет необходимости (и если вы действительно используете C , вам следует так и сказать) и может усложнить задачу в будущем.

  6. Вы никогда не проверяете возвращаемые значения malloc на предмет сбоя.

  7. Вы используете counter указатель вне функции, в которой он объявлен. Вне вызова функции вы должны использовать count переменную, которую вы передали в качестве параметра. Параметры функции не продолжают существовать вне функций, в которых они используются.

Ответ №3:

Основные проблемы:

  1. Ваши типы не совпадают. При вызове getRegEx(amp;count, amp;keys) тип выражения amp;keys является char *** , а не char ** . Обратите внимание, что если вы хотите изменить значение keys , вам придется передать указатель на него. Это приводит к следующей проблеме…

  2. Поскольку вы изменяете значение параметра 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 оператор!