0

If a function returns me a pointer to a uint8_t array of dynamic/unknown size, how can I fill up my local array using that pointer?

uint8_t * func(void){

uint8_t bs[] = {0x34, 0x89, 0xa5}; //size is variant

return bs;

}

void main(void){

uint8_t * p;

static uint8_t myArr[10]; //size is always greater than what's expected from p

p = func();

}

How can i use p to fill up myArr which could be of different sizes at different calls? Is this possible to determine the size of the array, p is pointing to?

Please excuse my very little experience with programming! Thanks.

xMaster
  • 33
  • 1
  • 7
  • 2
    No, it is not. And in your example, `func` is returning a pointer to a local array. That array ceases to exist as soon as func returns. So `p` in main points to memory you have no right to use at all. – Mat May 02 '15 at 04:43
  • returning `bs`in `func` causes UB, don't do it – user3528438 May 02 '15 at 04:43
  • yeah, that also is an issue, [here is a past question about it](http://stackoverflow.com/questions/4570366/pointer-to-local-variable) – Diego May 02 '15 at 04:46
  • 1
    @user3528438 returning it doesn't cause undefined behavior. Dereferencing it does. – rowan.G May 02 '15 at 05:34
  • What if the pointer being returned is of global scope? we still need the size, right? – xMaster May 02 '15 at 05:37
  • @rowan.G `p = func();` causes undefined behaviour even if `p` is not dereferenced. (I'm not sure if `func()` by itself does; probably not) – M.M May 02 '15 at 05:52

2 Answers2

0

you can't do it like you want to.

the array size needs to known to copy it with memcpy() and you cannot return any automatic variables outside of their scope. the array in your function is gone once you leave the function. You either have to heap allocate it with malloc() and friends or make it static.

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>

uint8_t *func(size_t *size) {

    uint8_t local_bs[] = {0x34, 0x89, 0xa5}; //size is variant
    uint8_t *bs;
    *size = sizeof(local_bs);

    bs = malloc(sizeof(uint8_t) * (*size));
    if (bs == NULL) {
        // allocation error return or exit here.
    }

    memcpy(bs, local_bs, sizeof(uint8_t) * (*size));

    return bs;

}

int main(){

    uint8_t *p;
    size_t *size = malloc(sizeof(size_t));
    if (size == NULL) {
        // allocation error return or exit here.
    }
    size_t i;

    p = func(size);

    // do stuff here with p
    for (i = 0; i < *size; i++) { 
        printf("%"PRIx8"\n", p[i]);
    }

    // need to cleanup the manually allocated p
    free(p);

}
rowan.G
  • 717
  • 7
  • 13
0

While most other answers and comments have addressed the undefined behavior in OP's example code. I am attempting to answer "copying a pointer to a uint8_t array of dynamic/unknown size and how can the OP fill up a local array using that pointer"

  1. You need to explicitly pass the size/length of the dynamic memory like so: uint8_t *func(size_t *size) as pointed out by rowan G's answer

  2. Or, you need to have a sentinel value to mark end of your data in memory, like the '\0' used by strings in C to mark the end of string. In this case, you will be able to calculate the size by traversing the entire memory, wherever you need the size/length of that memory.

{0x34, 0x89, 0xa5, 0x00}; // size depends on the position of 0x00 and ofcourse bound by memory allocated

askmish
  • 6,464
  • 23
  • 42
  • 1
    ...or the "sentinel" may be a *lead* value, akin to a Pascal string, thus avoiding the hun-for-length scanning operation. Or, since length and data are tightly related, a `struct`, which can be returned by-value with embedded dynamic pointer and size members. There are multiple options. – WhozCraig May 02 '15 at 08:42
  • @WhozCraig Yes, that too. Plus one for that. – askmish May 02 '15 at 08:47