2016-02-14 4 views
0

Я вызываю функцию getdata() ниже внутри main(). getdata() читает символы из uart и помещает их в массив. В конце функции он выдает массив над uart.Как вернуть указатель на массив в c

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

Как я мог сделать это с помощью функции ниже, чтобы я мог записать данные в главном, а не делать это внутри getdata().

int main(void) 
{ 
    getdata(); 
} 

void getdata(void) 
{ 
    static uint8_t ndx; 
    char recChars[6]; 
    char retchar; 
    ndx = 0; 

    retchar = getch(); 
    recChars[ndx] = retchar; 
    ndx++; 

    if (retchar == '\r'){ 
     recChars[ndx] = '\n'; 
     ndx = 0; 
     uart_write(UART_D, (uint8_t *)recChars, sizeof(recChars)); 
    }    
} 

char getch(void) { 
uint8_t ch = 0; 
chuart_read(UART_D, &ch); 
return ((char) ch); 
} 
+0

Можете ли вы использовать стандартные библиотечные функции? (Вы не указываете какие-либо 'include', и ваше собственное определение 'getch' предполагает, что вы не можете.) – usr2564301

+0

Вам нужно объявить свою функцию как возвращающую указатель на char *, а также создать массив как указатель на char и распределить его динамически с помощью malloc, иначе данные будут удалены при выходе из функции. Я не запрограммировал в C какое-то время, поэтому я мог бы быть здесь. –

+0

По какой-либо причине вы используете правильный декларатор стиля прототипа для 'main' и' getch', но не для 'getdata', иначе вы используете устаревший старый стиль? – Olaf

ответ

2

Вам нужно сделать recChars указатель и выделить динамическую память для его использования malloc() или семьи. Затем вы можете вернуть указатель на вызывающий и использовать его в вызывающем.

Что-то вроде

char * getdata()   //change return type 
{ 
    static uint8_t ndx; 
    char * recChars = NULL; // change to pointer 
    char retchar; 
    ndx = 0; 

    if ((recChars = malloc(6)) == NULL) return NULL; 

    retchar = getch(); 
    recChars[ndx] = retchar; 
    ndx++; 

    if (retchar == '\r'){ 
     recChars[ndx] = '\n'; 
     ndx = 0; 
     //uart_write(UART_D, (uint8_t *)recChars, sizeof(recChars)); 
    }  

    return recChars;  //finally return 
} 

Помните, что возвращаемый указатель должен быть free() -d в вызывающем, после использования закончится, чтобы избежать утечки памяти.

+0

спасибо, что делает строка 'if ((recChars = malloc (6) == NULL) return NULL;' do? Также будет выглядеть мой 'main()'? Int main (void) {char * pointer = getdata(); uart_write (UART_D, (uint8_t *) recChars, sizeof (recChars)); free (pointer); return 0;} ' –

+0

Он проверяет возвращаемое значение' malloc', если это 'NULL', и вы сделали не передавайте '0' в качестве параметра, вы, вероятно, имеете ошибку« ENOMEM ». Также вы не можете вызывать' sizeof' в 'main', так как он возвращает размер указателя, а не количество элементов в массиве. массив '' \ 0'' завершен, вы должны использовать 'strlen'. Если это не' '\ 0'', то вы можете его закончить с' '\ 0''. –

1

Вы должны написать функцию, которая возвращает указатель на char и использовать malloc для выделения памяти. Вы должны использовать таНос, поскольку массивы объявлены как этого

char v[11]; 

относитесь к автоматическому классу хранения, который означает, что они имеют блок сферы, они удаляются, как только ваши возвратов функции и они не инициализируются по умолчанию. Вместо динамической памяти можно получить доступ в любом месте вашей программы, если у вас есть указатель на этот блок памяти. Вы также не забыли освободить память, используя free(), чтобы избежать утечки памяти. Если вы вернете указатель на автоматический массив, вы, вероятно, получите SIGSEGV, потому что ваш указатель держит ячейку памяти, которая больше не существует. Таким образом, вы могли бы написать что-то вроде этого:

char *foo(void) 
{ 
    char *p = malloc(sizeof(type) * n); 
    return p; 
} 

В главном

int main(void) 
{ 
    char *pointer = foo(); 
    /*Do something*/ 
    free(pointer); 
    return EXIT_SUCCESS; 
} 

PS: Прошу прощения за мой английский

0

Я бы посоветовал вам объявить массив в функции main() сам передать укажите ссылку на функцию getdata, поэтому при обновлении getdata(), который будет отображаться в массиве в main().

Примечание: Кстати, почему вы используете sizeof (recChars), который даст 6, но вы обновляете только до 2 местоположений. Я включить это также в коде

int main(void) 
{ 
    char recChars[6]; 
    int Rxd_Len = 0; 

    Rxd_Len = getdata(&recChars); //Pass the address of array 
    uart_write(UART_D, (uint8_t *)recChars, Rxd_Len); 
} 

int getdata(char *ptr_recChars) 
{ 
    uint8_t ndx; // removed static since its not a required/mandatory 
    char retchar; 
    ndx = 0; 

    retchar = getch(); 

    *(ptr_recChars + ndx) = retchar; //Asign the value to the array address + offset 


    if (retchar == '\r'){ 
     ndx++; 
     *(ptr_recChars + ndx) = '\n'; 

    } 

    return ndx;   
} 

char getch(void) { 
uint8_t ch = 0; 
int ret; 
ret = uart_read(UART_D, &ch); 
return ((char) ch); 
} 

UPDATE:

Это нормально называть uart_write() в основной()? Да, вы можете это сделать, но так как uart_write() будет использовать длину для передачи, вам нужно отслеживать ее, используя другую переменную.

Кроме того, почему эта линия необходима? Что он делает *(ptr_recChars + ndx) = retchar;? ptr_recChars указатель, который указывает на массив recChars[6], поэтому с помощью этого указателя можно обновить массив recChars[6], даже если он объявлен в main(), *(ptr_recChars + ndx), здесь ndx является 0 так обновляется первый элемент массива, то после этого вам приращение ndx затем, используя переменный указатель, мы можем указать на новое обновленном место на *(ptr_recChars + ndx)ndx новым значением в настоящее время)

Кроме того, я должен & оператора в GetData (& recChars); Нет, имя массива само по себе является указателем, поэтому для recChars[6] simplay, дающий recChars, предоставит базовый адрес массива, а также примечание recChars и &recChars[0] означает то же самое. Так что если вы дадите &recChars, значит, recChars - это адрес, а затем добавление &recChars принимает адрес адреса, который даст вам недопустимое значение в вашем выражении.

+0

спасибо, что я хотел сделать. ok для вызова 'uart_write()' в 'main()'? –

+0

Кроме того, почему эта строка необходима? Что она делает? Спасибо '* (ptr_recChars + ndx) = retchar; // Присвоить значение массиву address + offset' –

+0

Кроме того, я должен '' 'оператор в' getdata (& recChars); '? спасибо –

0

Вы можете написать функцию, которая возвращает char *, и использовать malloc для создания некоторого хранилища для этой таблицы, как упомянуто выше, или вы можете просто объявить свой массив как статический и вернуть его. В более явном виде:

char * getdata (void) { static char retChar [6]; ... return retChar; }

Работы. Причина этого в том, что хранилище массивов зарезервировано в специальном сегменте.

версия с таНосом оставляет за собой хранилище для массива в куче, которая требует от вас, чтобы освободить его впоследствии:

символ * GetData (недействительный) { символа * retChar = (символ *) таНос (6) ; ... return retChar; }

основное() { char * ptr = getdata(); ... free (ptr); }

Наконец, единственным, что вы не можете сделать, это объявить массив и возвращает его как есть, без статической декларации и не таНоса ... Причина этого заключается в том, что ваш массив выделяется в вызове -stack, и поэтому потенциально теряется, когда вы возвращаете из getdata. Другими словами, никогда не делайте: char * getdata (void) { char retChar [6]; ... return retChar; }

+0

'char *' не является указателем на массив! И в 'static' array есть другие проблемы, о которых вы даже не упоминаете. – Olaf

+0

Извините, я не вижу, где я утверждаю, что char * является «указателем на массив». – user5922822

+0

Извините, я, кажется, слишком толковал текст. Однако второе предложение стоит. Кроме того, C не требует использования стека, поэтому любая ссылка на этом уровне не имеет значения. Вы должны были просто сказать, что говорится в стандарте: доступ к прошлому - это UB. И вы имеете в виду определение, а не просто объявление. – Olaf

Смежные вопросы