如何在c中返回指向数组的指针

时间:2016-02-14 13:48:46

标签: c arrays function pointers return-value

我在main()中调用下面的函数getdata()getdata()从uart中读取字符并将它们放入数组中。在函数结束时,它通过uart写出数组。

我的问题是,如何让这个函数返回数据?我知道你不能在c中返回数组,你应该声明一个返回指针的函数。

如何使用下面的函数执行此操作,以便我可以在main中写出数据,而不必在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);
}

4 个答案:

答案 0 :(得分:2)

您需要使public int Print(DatabaseConnector dc) { try { // Set up PrintDocument PrintDocument recordDoc = new PrintDocument(); recordDoc.DocumentName = "PrintTask ID "+id.ToString(); recordDoc.PrintPage += new PrintPageEventHandler(PrintTask.PrintReceiptPage); // Filling in the stuff // Print Controller StandardPrintController spc = new StandardPrintController(); recordDoc.PrintController = spc; // This hides popup // Printer Settings PrinterSettings ps = new PrinterSettings(); ps.PrinterName = dc.ReadSetting("PrinterName"); recordDoc.PrinterSettings = ps; recordDoc.Print(); // Clean up recordDoc.Dispose(); } catch (Exception exc) { ((MainForm)Application.OpenForms[0]).msg(exc.Message); } return 1; // ignore this } private static void PrintReceiptPage(object sender, PrintPageEventArgs e) { try { // Read settings DatabaseConnector db = new DatabaseConnector(); PrintTask pt = db.ReadTask(); float x = float.Parse(db.ReadSetting("PaperMarginFromLeft")); float y = float.Parse(db.ReadSetting("PaperMarginFromTop")); float width = float.Parse(db.ReadSetting("PaperWidth")); float height = 0F; string text; // Set up font Font drawFont1 = new Font(db.ReadSetting("PrintFont"), Int32.Parse(db.ReadSetting("PrintFontSize")), FontStyle.Regular); SolidBrush drawBrush = new SolidBrush(Color.Black); // Set format of string. StringFormat drawFormatLeft = new StringFormat(); drawFormatLeft.Alignment = StringAlignment.Near; // Draw string to screen. text = pt.getData(); e.Graphics.DrawString(text, drawFont1, drawBrush, new RectangleF(x, y, width, height), drawFormatLeft); // calculate text size SizeF textSize = e.Graphics.MeasureString(text, drawFont1); y += textSize.Height; // Set page size - has no effect e.HasMorePages = false; float inchHeight = PrintTask.PixelsToInchY(y, e.Graphics); PaperSize originalPaperSize = e.PageSettings.PaperSize; PaperSize scaledSize = new PaperSize("Custom", originalPaperSize.Width, (int)Math.Ceiling(inchHeight * 100)); e.PageSettings.PaperSize = scaledSize; e.PageSettings.PrinterSettings.DefaultPageSettings.PaperSize = scaledSize; } catch (Exception exc) { ((MainForm)Application.OpenForms[0]).msg(exc.Message); } } public static float PixelsToInchX(float n, Graphics graphics) { return n * graphics.DpiX / 300; } public static float PixelsToInchY(float n, Graphics graphics) { return n * graphics.DpiY / 300; } 指针并使用malloc()或系列为其分配动态内存。然后,您可以将指针返回给调用者并在调用者中使用它。

这样的东西
recChars

请记住,在使用结束后,返回的指针需要在调用者中为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 } - d,以避免内存泄漏。

答案 1 :(得分:1)

您必须编写一个函数,该函数返回指向char的指针并使用malloc来分配内存。您必须使用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:我为我的英语道歉

答案 2 :(得分:0)

我建议你在main()函数本身声明一个数组,将arrray作为对getdata函数的引用传递,所以只要getdata()得到更新,就会反映在{{1}中的数组中}。

注意:顺便说一下你为什么使用sizeof(recChars),这将给出6,但你只能更新2个位置。我也在代码中加入了这个

main()

更新:

可以在main()中调用uart_write()吗? 是的,你可以这样做,但由于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); } 将使用传输长度,你需要使用另一个变量来跟踪它。

另外,为什么这条线是必要的?它做什么uart_write() ptr_recChars是一个指向数组*(ptr_recChars + ndx) = retchar;的指针,所以使用这个指针我们可以更新数组recChars[6],即使它在recChars[6]main()中声明,*(ptr_recChars + ndx) 1}}是ndx所以数组的第一个元素被更新,然后你增加0然后,使用指针变量我们可以指向ndx新的更新位置(因为*(ptr_recChars + ndx)现在是新值)

另外,我应该& getdata中的运算符(& recChars); 不,数组名称本身就是一个指针,因此ndx simplay单独给出recChars[6]将给出数组的基址,同时注意recCharsrecChars表示相同。因此,如果您提供&recChars[0],则表示&recChars是一个地址,然后添加recChars会假定地址的地址会在您的表达式中为您提供无效值。

答案 3 :(得分:0)

如上所述,您可以编写一个返回char *并使用malloc为此表创建一些存储的函数,或者您可以简单地将您的数组声明为静态并返回它。 更明确地说:

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

作品。原因是阵列存储在特殊段中保留。

使用malloc的版本为堆中的数组保留存储空间,这需要您以后释放它:

char * getdata(void){   char * retChar =(char *)malloc(6);   ...   返回retChar; }

main(){   char * ptr = getdata();   ...   免费(PTR); }

最后你唯一不能做的就是声明数组并按原样返回它,没有静态声明,也没有malloc ......原因是你的 数组在调用堆栈中分配,因此在返回时可能会丢失 来自getdata。 换句话说,永远不要做: char * getdata(void){   char retChar [6];   ...   返回retChar; }