从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
返回一个指向7uint8\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
正在返回一个指向7uint8\u t
(拼写为uint8)数组的指针_