Возврат массива указателей на символы - PullRequest
4 голосов
/ 22 января 2010

Я пытаюсь вернуть массив char* в функцию. Я упростил свой код до контрольного примера, который клонирует массив символов, который вместо содержащих символы содержит указатели на эти символы.

/*
 * code.c
 */
#include <stdio.h>

char* makePointerCopy(char cIn[]);

int main() {
    char cTest[] = {'c', 't', 's', 't'};
    char* cPTest[] = makePointerCopy(cTest);
    printf("%p %c", cPTest, *cPTest);
    fflush(stdout);
    return 0;
}

char* makePointerCopy(char cIn[]) {
    char* cOut[sizeof(cIn)/sizeof(cIn[0])];
    int iCntr;

    for (iCntr = 0; iCntr < sizeof(cIn)/sizeof(cIn[0]); iCntr++)
        cOut[iCntr] = cIn + iCntr;

    return cOut;
}

Пара предупреждений, вот что должен сказать компилятор об этом фрагменте кода:

неверный инициализатор (при char* cPTest[] = makePointerCopy(cTest);)

Почему это происходит?

Ответы [ 8 ]

5 голосов
/ 22 января 2010

Поскольку makePointerCopy возвращает char*, а не char*[].

Вы должны иметь возможность изменить эту строку на:

char* cPTest = makePointerCopy(cTest);

Более конкретно, причина того, что вы получаете сообщение об ошибке TH, а не что-то о типах, заключается в том, что инициализаторы массива должны быть константами времени компиляции.

С http://bytes.com/topic/c/answers/215573-invalid-initializer

Даже если декларация отсутствует в файле сфера, это было бы незаконно в обоих C90 и C99. C90 требует времени компиляции постоянные инициализаторы для автоматического и зарегистрировать массивы. И оба C90 и C99 требует, чтобы массив символов был инициализируется а) строковым литералом, или б) заключенный в скобки инициализатор список.

Тем не менее, несоответствие типов является актуальной проблемой.

3 голосов
/ 22 января 2010

В этой строке вы пытаетесь присвоить char * массиву char *. Проще говоря, они бывают разных типов.

2 голосов
/ 22 января 2010

Давайте начнем с предупреждения. Вы заявили:

char* cPTest[]

на английском языке: "cPTest - массив указателей на символ "

и

char* makePointerCopy(char cIn[]);

на английском языке: "makePointerCopy() принимает массив символов и возвращает указатель на символ "

Итак, вы пытаетесь присвоить " указатель на символ " на " массив указателей на символы ". Вы видите проблему? Я бы посоветовал тщательно проверить типы перед выполнением заданий.

Тем не менее, вы действительно хотите объявить makePointerCopy(), чтобы вернуть «указатель на указатель на символ»:

char **makePointerCopy(char cIn[]);

потому что в конце вы вернете указатель на первый элемент возвращаемого массива.

Еще один важный момент: вы объявили «cOut» в качестве локальной переменной для функции.

char* makePointerCopy(char cIn[]) {
    char* cOut[sizeof(cIn)/sizeof(cIn[0])];

    ...  /* cOut can ONLY be used within the function! */

    return cOut;  // <-- The address returned point to a 
                  //     block of memory that is no longer valid
                  //     after the end of the function
}

Помните, что локальные переменные автоматически становятся недействительными после завершения функции. Чтобы «сохранить» его, вы можете объявить его static:

char* makePointerCopy(char cIn[]) {
    static char* cOut[sizeof(cIn)/sizeof(cIn[0])];

    ...  /* cOut will survive the end of the function */

    return cOut;  // <-- The address can be returned 
}

Обратите внимание, что вы должны быть хорошо дисциплинированными при возврате значений такого типа.

В качестве альтернативы вы можете выделить необходимое пространство с помощью malloc(), если вы будете помнить free(), когда оно вам больше не нужно.

2 голосов
/ 22 января 2010

Поскольку ваша функция возвращает char*, пока вы присваиваете ей char*[]. C может иметь довольно слабую систему типов, но некоторые вещи не должны быть выполнены: -)

2 голосов
/ 22 января 2010

Вам необходимо вернуть char ** или char *[].

В частности, если вы хотите, чтобы makePointerCopy возвратил "массив char*, тогда вам нужно фактически вернуть такой массив. Прямо сейчас вы возвращаете указатель на char или" char* " .

Строка кода, о которой идет речь, пытается присвоить результат makePointerCopy, который возвращает char* для char*[]. Хотя это технически нормально в C, и компилятор все равно выдаст результат, компилятор в основном информирует вас о том, что то, что он производит, может на самом деле не выполняться так, как вы ожидаете.

1 голос
/ 22 января 2010

Все остальные ответы верны, но, похоже, с вашим кодом довольно много других проблем:

char* cOut[sizeof(cIn)/sizeof(cIn[0])];

Я полагаю, вы думаете, что sizeof (cIn) возвращает объем памяти, занимаемый элементами в массиве cIn. Это неверно. В этом случае sizeof (cIn) вернет размер указателя в вашей системе, обычно 4 или 8 байт. sizeof (cIn [0]) вернет размер символа, который составляет 1 байт. Как правило, нет способа определить размер массива в C, поэтому я боюсь, что вам придется передать этот размер вашей функции.

Также имейте в виду, что makePointerCopy возвращает указатель на статически выделенный блок памяти. Эта память в основном является локальной переменной makePointerCopy и будет освобождена, когда makePointerCopy закончит свою работу. Другими словами, makePointerCopy вернет указатель на недопустимую память.

0 голосов
/ 22 января 2010

char * - указатель на один символ, где вам нужно char **, который является указателем на массив или char *

0 голосов
/ 22 января 2010

Функция возвращает символ *, а не символ [] *.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...