C语言 从 C 函数返回指向 uint8_t 数组的指针 - 获取编译器错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23597259/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 11:04:52  来源:igfitidea点击:

returning a pointer to an array of uint8_t from a C function - get compiler errors

cuint8t

提问by banditKing

I have a function:

我有一个功能:

uint8_t*  createTestBuffer()
{

    uint8_t buffer[] = {5,7,3,4,1,9,3};
    return &buffer;
}

runing it:

运行它:

uint8_t *buff = createTestBuffer();

returns compiler errors:

返回编译器错误:

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;

Im returning a pointer to an array of uint8_t from my function. So what am I getting wrong here?

我从我的函数返回一个指向 uint8_t 数组的指针。那么我在这里做错了什么?

回答by Jonathan Leffler

The compiler told you that return &buffer;is returning a pointer to an array of 7 uint8_t(spelled uint8_t (*)[7]), but you said the function returns uint8_t *, and these are different and incompatible pointer types.

编译器告诉你return &buffer;返回一个指向 7 数组的指针uint8_t(拼写为uint8_t (*)[7]),但你说函数返回uint8_t *,这些是不同且不兼容的指针类型。

If you wrote return buffer;, the types would be correct but the code would still be wrong. You can't safely return a pointer to a local array that's on the stack.

如果您编写return buffer;,类型将是正确的,但代码仍然是错误的。您不能安全地返回指向堆栈上的本地数组的指针。

Either make it static const uint8_t buffer[] = { … };and change the function return type to const uint8_t *, and use accordingly (which is thread-safe because the data never changes):

要么制作它static const uint8_t buffer[] = { … };并将函数返回类型更改为const uint8_t *,并相应地使用(这是线程安全的,因为数据永远不会改变):

const uint8_t *createTestBuffer(void)
{
    static const uint8_t buffer[] = { 5, 7, 3, 4, 9, 1, 3 };
    return buffer;
}

Or use dynamic allocation in some form as:

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

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;
}

Note that the calling code here needs to check that it gets a non-null pointer back again, and it must also ensure it calls free()on the returned pointer unless it is null (when calling free()becomes optional).

请注意,这里的调用代码需要检查它是否再次获取了非空指针,并且还必须确保它调用free()返回的指针,除非它为空(当调用free()变为可选时)。

Or make the caller pass the buffer – living dangerously by assuming that the user knows to pass enough space:

或者让调用者传递缓冲区——通过假设用户知道传递足够的空间来危险地生活:

void createTestBuffer(uint8_t *output)
{
    static const uint8_t buffer[] = { 5, 7, 3, 4, 9, 1, 3 };
    memmove(output, buffer, sizeof(buffer));
}

Or living less dangerously:

或者活得不那么危险:

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));
}

There are other ways to handle 'output buffer smaller than copied buffer'; this code copied as much as was safe, but you could return a 0 or 1 status indicating truncation, or assert that the supplied length is not smaller than the required length, or …

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

回答by zmo

here you have two errors:

在这里你有两个错误:

your first error, is that you're returning your buffer using the &operator (aka address of), which gives a pointer to your variable's address. Your array being already uint8_t*you're returning uint8_t(*)[7], as the error is telling you. And the compiler is grumpy, because you're trying to return that one whereas your function shall return the former.

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

But know that actually there's an even more important error in your code, as first spotted out by @TimCooper:

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

you're allocating a variable within the scope of a function, and want to use it outside of that function. In C, when you declare a variable within a function, the memory used to allocated it is freed upon exit of that function, so even if you correct the typing of your function that won't work as expected.

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

You need to either declare your uint8_t array outside of the function, and pass it as a parameter to your function:

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

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;
}

or you need to use malloc to allocate the memory in the heap instead of allocating it in the stack:

或者您需要使用 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;
}

but then you'll have to not forget to free()the buffer variable once you've finished using it.

但是free()一旦你用完它,你就必须不要忘记缓冲区变量。

回答by ezaquarii

You get the warning because bufferis of type uint8_t*. The statement &bufferis of type uint8_t**- a pointer to a pointer.

您收到警告是因为buffer类型为uint8_t*。该语句&buffer属于类型uint8_t**- 指向指针的指针。

In C and C++ an array name is the same as a pointer.

在 C 和 C++ 中,数组名称与指针相同。

char s[4] = { 'a', 'b', 'c', '
uint8_t* createTestBuffer()
{
    uint8_t *buffer = (char*)malloc( 3 * sizeof(char) );
    buffer[0] = 10;
    buffer[1] = 20;
    buffer[2] = 30;
    return buffer;
}
' }; char *p = &s[0]; printf("%s", s); printf("%s", p);

The second thing is that you're returning a pointer to an array CREATED ON STACK. This array is not valid after function exit. In practice you're returning a dangling pointer.

第二件事是您要返回一个指向在堆栈上创建的数组的指针。该数组在函数退出后无效。实际上,您返回的是一个悬空指针。

If you want to return a pointer you should allocate memory on heap, using malloc():

如果你想返回一个指针,你应该在堆上分配内存,使用malloc()

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;
}

But there is another problem. You're returning a pointer to a memory block, but you don't know how big the buffer is. You can modify the function to "return" 2 values this way:

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

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

and call it like this:

并这样称呼它:

##代码##

Enjoy!

享受!