Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/extjs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从C函数返回指向uint8_t数组的指针-get编译器错误_C_Uint8t - Fatal编程技术网

从C函数返回指向uint8_t数组的指针-get编译器错误

从C函数返回指向uint8_t数组的指针-get编译器错误,c,uint8t,C,Uint8t,我有一个功能: uint8_t* createTestBuffer() { uint8_t buffer[] = {5,7,3,4,1,9,3}; return &buffer; } uint8_t* createTestBuffer(uint8_t* array) { array[0] = 5; array[1] = 7; array[2] = 3; array[3] = 4; array[4] = 1; array

我有一个功能:

uint8_t*  createTestBuffer()
{

    uint8_t buffer[] = {5,7,3,4,1,9,3};
    return &buffer;
}
uint8_t* createTestBuffer(uint8_t* array) {
    array[0] = 5;
    array[1] = 7;
    array[2] = 3;
    array[3] = 4;
    array[4] = 1;
    array[5] = 9;
    array[6] = 3;
    return array;
}
运行它:

uint8_t *buff = createTestBuffer();
返回编译器错误:

c_programming.c:11:9: warning: incompatible pointer types returning 'uint8_t (*)[7]' from a function with result type
      'uint8_t *' (aka 'unsigned char *') [-Wincompatible-pointer-types]
        return &buffer;

我从函数返回一个指向uint8\u t数组的指针。那么,我这里出了什么问题呢?

您会收到警告,因为
缓冲区
的类型是
uint8\u t*
。语句
&buffer
的类型为
uint8\u t**
——指向指针的指针

<>在C和C++中,数组名称与指针相同。
char s[4] = { 'a', 'b', 'c', '\0' };
char *p = &s[0];
printf("%s", s);
printf("%s", p);
第二件事是返回一个指向在堆栈上创建的数组的指针。此数组在函数退出后无效。实际上,您返回的是一个悬空指针

如果要返回指针,应使用
malloc()
,在堆上分配内存:

但还有另一个问题。返回指向内存块的指针,但不知道缓冲区有多大。您可以通过以下方式修改函数以“返回”2个值:

void createTestBuffer(uint8_t **buffer, size_t *size)
{
    *buffer = (char*)malloc( 3 * sizeof(char) );
    buffer[0] = 10;
    buffer[1] = 20;
    buffer[2] = 30;
    *size = 3;
}
这样称呼它:

char *buf;
size_t size;
createTestBuffer(&buf, &size);

享受吧

您会收到警告,因为
缓冲区
的类型为
uint8\u t*
。语句
&buffer
的类型为
uint8\u t**
——指向指针的指针

<>在C和C++中,数组名称与指针相同。
char s[4] = { 'a', 'b', 'c', '\0' };
char *p = &s[0];
printf("%s", s);
printf("%s", p);
第二件事是返回一个指向在堆栈上创建的数组的指针。此数组在函数退出后无效。实际上,您返回的是一个悬空指针

如果要返回指针,应使用
malloc()
,在堆上分配内存:

但还有另一个问题。返回指向内存块的指针,但不知道缓冲区有多大。您可以通过以下方式修改函数以“返回”2个值:

void createTestBuffer(uint8_t **buffer, size_t *size)
{
    *buffer = (char*)malloc( 3 * sizeof(char) );
    buffer[0] = 10;
    buffer[1] = 20;
    buffer[2] = 30;
    *size = 3;
}
这样称呼它:

char *buf;
size_t size;
createTestBuffer(&buf, &size);

享受吧

这里有两个错误:

您的第一个错误是,您正在使用
&
运算符(又名address of)返回缓冲区,该运算符提供指向变量地址的指针。正如错误告诉您的那样,您的数组已经被
uint8\u t*
返回
uint8\u t(*)[7]
。而编译器是脾气暴躁的,因为你试图返回那个,而你的函数应该返回前者

但要知道,实际上,正如@TimCooper首先发现的那样,代码中还有一个更重要的错误:

您在函数范围内分配变量,并希望在该函数之外使用它。在C语言中,当您在一个函数中声明一个变量时,用于分配它的内存在该函数退出时会被释放,因此即使您更正了函数的类型,它也不会按预期工作

您需要在函数外部声明uint8_t数组,并将其作为参数传递给函数:

uint8_t*  createTestBuffer()
{

    uint8_t buffer[] = {5,7,3,4,1,9,3};
    return &buffer;
}
uint8_t* createTestBuffer(uint8_t* array) {
    array[0] = 5;
    array[1] = 7;
    array[2] = 3;
    array[3] = 4;
    array[4] = 1;
    array[5] = 9;
    array[6] = 3;
    return array;
}
或者您需要使用malloc在堆中分配内存,而不是在堆栈中分配内存:

uint8_t* createTestBuffer() {
    uint8_t* array = , malloc(sizeof(uint8_t)*7);
    array[0] = 5;
    array[1] = 7;
    array[2] = 3;
    array[3] = 4;
    array[4] = 1;
    array[5] = 9;
    array[6] = 3;
    return array;
}

但是,在使用完缓冲区变量后,不要忘记释放它。

这里有两个错误:

您的第一个错误是,您正在使用
&
运算符(又名address of)返回缓冲区,该运算符提供指向变量地址的指针。正如错误告诉您的那样,您的数组已经被
uint8\u t*
返回
uint8\u t(*)[7]
。而编译器是脾气暴躁的,因为你试图返回那个,而你的函数应该返回前者

但要知道,实际上,正如@TimCooper首先发现的那样,代码中还有一个更重要的错误:

您在函数范围内分配变量,并希望在该函数之外使用它。在C语言中,当您在一个函数中声明一个变量时,用于分配它的内存在该函数退出时会被释放,因此即使您更正了函数的类型,它也不会按预期工作

您需要在函数外部声明uint8_t数组,并将其作为参数传递给函数:

uint8_t*  createTestBuffer()
{

    uint8_t buffer[] = {5,7,3,4,1,9,3};
    return &buffer;
}
uint8_t* createTestBuffer(uint8_t* array) {
    array[0] = 5;
    array[1] = 7;
    array[2] = 3;
    array[3] = 4;
    array[4] = 1;
    array[5] = 9;
    array[6] = 3;
    return array;
}
或者您需要使用malloc在堆中分配内存,而不是在堆栈中分配内存:

uint8_t* createTestBuffer() {
    uint8_t* array = , malloc(sizeof(uint8_t)*7);
    array[0] = 5;
    array[1] = 7;
    array[2] = 3;
    array[3] = 4;
    array[4] = 1;
    array[5] = 9;
    array[6] = 3;
    return array;
}

但是,一旦使用完buffer变量,就不要忘记释放它。

编译器告诉您,
返回&buffer
返回一个指向7
uint8\u t
(拼写为
uint8\u t(*)[7]
)数组的指针,但您说函数返回
uint8\u t*
,这是不同且不兼容的指针类型

如果编写
返回缓冲区,类型将是正确的,但代码仍然是错误的。您无法安全地返回指向堆栈上本地数组的指针

要么使其
静态常量8_t buffer[]={…}
并将函数返回类型更改为
const uint8\u t*
,并相应地使用(这是线程安全的,因为数据从不更改):

或者以某种形式使用动态分配,如:

uint8_t *createTestBuffer(void)
{
    static const uint8_t buffer[] = { 5, 7, 3, 4, 9, 1, 3 };
    uint8_t *rv = malloc(sizeof(buffer));
    if (rv != 0)
        memmove(rv, buffer, sizeof(buffer));
    return rv;
}
请注意,这里的调用代码需要检查它是否再次获取非空指针,并且它还必须确保在返回的指针上调用
free()
,除非它为空(当调用
free()
成为可选时)

或者让调用者通过缓冲区——假设用户知道要通过足够的空间,这样做是危险的:

void createTestBuffer(uint8_t *output)
{
    static const uint8_t buffer[] = { 5, 7, 3, 4, 9, 1, 3 };
    memmove(output, buffer, sizeof(buffer));
}
或者生活得不那么危险:

static inline size_t min(size_t a, size_t b) { return (a < b) ? a : b; }

void createTestBuffer(uint8_t *output, size_t outlen)
{
    static const uint8_t buffer[] = { 5, 7, 3, 4, 9, 1, 3 };
    memmove(output, buffer, min(sizeof(buffer), outlen));
}
staticinlinesize\utmin(size\uta,size\utb){return(a

还有其他处理“输出缓冲区小于复制缓冲区”的方法;此代码尽可能安全地复制,但您可以返回表示截断的0或1状态,或者断言提供的长度不小于所需的长度,或者…

编译器告诉您
返回&buffer
正在返回一个指向7
uint8\u t
(拼写为
uint8)数组的指针_