简体   繁体   中英

Why doesn't C function with char** param set value of a pointer to char[] arg

My source file has a function, which I invoke in the process of de-serializing a struct passed over a C socket (this is the client source):

MY_STRUCT_TYPE myStructVar;

unsigned char * deserialize_chararr(unsigned char *buffer, unsigned char** value)
{
    unsigned char val[256];
    int i;
    for(i = 0; buffer[i]; i++) {
        val[i] = buffer[i];
    }
    val[i++] = '\0';
    printf("\n chararr: %s :", val);

    *value = malloc(i * sizeof **value);
    for(i = 0; buffer[i]; i++) {
        (*value)[i] = buffer[i];
        printf("%c", (*value)[i]);
    }
    (*value)[i++] = '\0';
    /* buffer contains a serialized struct read over a socket using recv. 
so this call returns the buffer pointer that get's passed to the next deserialize_<type> invocation a la https://stackoverflow.com/a/1577174/434145
That's why the first string extraction followed by an attempt to set it in the struct as part of unpacking. */
    return buffer + i;
}

that I'm calling as

buffer = deserialize_chararr(buffer, &myStructVar->szrecordid);

where

typedef struct _MY_STRUCT_TYPE {
    unsigned char   szrecordid[28];
}

The server sends the data alright and it even parses correctly in the above function, but I can't seem to be able to set it in the String variable of my struct. I changed my function to use char ** param after seeing this , but still get rubbish when I print

printf("\n Payload:"  "\n szrecordid: %s ", myStructVar.szrecordid);

In short, I pass a pointer to a string (&myStructVar->szrecordid), use malloc and assign my pointee character by charcter (this latter part I got from the link ). Both before and after I changed the code from using a char * to using a char ** I was getting the same error and a compiler warning:

client.c:159: warning: passing arg 2 of `deserialize_chararr' from incompatible pointer type

So what am I doing wrong?

The problem is that a pointer to an array is not compatible with a pointer to a pointer. They are different things. And it's a good thing too, because this is meant to catch errors like the one in your code. What you are doing is basically this:

unsigned char szrecordid[28];
szrecordid = malloc(i * sizeof **value);

You should be able to see the problem; you're trying to assign a pointer to an array.

If I understand correctly, your problem is that you can't change the address of szrecordid:

typedef struct _MY_STRUCT_TYPE {
    unsigned char   szrecordid[28];
}

And if you can't change the address of this variable it's because it's an array. Try using a char * instead or don't malloc and use strcpy instead.

By the way, please consider using strcpy and strdup when you can. Basically, your function is doing:

strcpy(val, buffer);
printf("\n chararr: %s :", val);
*value = strdup(buffer);
printf("%s", value);

And you could also notice that the first strcpy is useless too. I don't understand the meaning of this intermediate char array.

szrecordid is an array of unsigned characters, not a pointer, so when you taks its address ( &myStructVar->szrecordid ) you get a pointer to an array (an unsigned char (*)[28] ), and not a pointer to a pointer, which is what the function expects.

If you think about it, it makes perfect sense -- you can't move an array by simply changing its address, as its address (and size) is fixed at the time it is allocated (when you create whatever it is that myStructVar points at). If you want to change that array, you need to change its contents by copying into into it, and that won't change the size, which is fixed at 28.

The obvious solution to your problem is make it a pointer instead of an array:

typedef struct _MY_STRUCT_TYPE {
    unsigned char   *szrecordid;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM