2

Looking the following approach of initializing a structure, you can see that malloc was not used to allocate a size for params in the main, it just pointed to to array right away. It prints the values correctly but is this valid practice/ what difference does it make if I allocate a size before the assignment?

typedef struct _param_t {
    char * params;
} param_t;

int main()
{
    int i;
    param_t r;
    unsigned char array[5] = {0x01 , 0x02 ,0x03 ,0x04 ,0xFF};
    r.params = (char *) array;
    
    for (i = 0; i < 5; i++) {
        printf(" Array %d is %x", i, r.params[i]);
    }
    
    return 0;
}

Output:

Array 0 is 1 Array 1 is 2 Array 2 is 3 Array 3 is 4 Array 4 is ffffffff               

On another note, this is the prototype of fwrite used to write to a file:

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
             

It takes in a void pointer. In the main, I cast the array to a (char *) to populate the structure. I know that converting between signed T* and unsigned T* in either direction is generally possible.

My questions is, what is the difference between writing r.params to a file in binary mode with sizeof(unsigned char) as size VS sizeof(char) as the size parameter ? Both are the same size. Therefore is shouldn't make a difference and reading from the file can then be stored in a char array or an unsigned char array without loss of data, correct?

Sarah cartenz
  • 1,313
  • 2
  • 14
  • 37
  • 1
    In binary mode, `fread` and `fwrite` do not care *what* the data is. They just operate on the size of data at the location you specify. The buffer they take is `const void *buffer` so the functions have no way of knowing anything about the data. – Weather Vane Aug 17 '20 at 07:17
  • As a side note, don’t use char(which can be signed or unsigned) when working with bytes always use unsigned char. – Fredrik Aug 17 '20 at 07:44
  • Re “converting between signed T* and unsigned T* in either direction is generally possible”: The answers you link to do not say that. The question is for character types, not a general type T. Character types are special in C and C++. – Eric Postpischil Aug 17 '20 at 09:39

2 Answers2

0

There shouldn't be any differences. The C standard requirements on character types are rather strict: must be 1 byte, must not contain padding bits or trap representations. It is therefore very likely that char and unsigned char have the same binary representation, regardless of if char is signed or unsigned on the given system. It is also perfectly safe to convert between the different character types.

Generally, when you want to use raw binary representations, use uint8_t instead, never char.

As you noted, printf family of functions will promote small integer types to int though. So in case char is signed, an impl.defined conversion to 2's complement negative number will happen in the 0xFF case. Upon promotion to 32 bit int, this is "sign extended into" 0xFFFFFFFF, which is then printed as an unsigned number using the %x specifier, that expects type unsigned int.

Lundin
  • 195,001
  • 40
  • 254
  • 396
-2

No

Answer to your question is no.

Data is always stored as binary

Data types in programming languages only exists for the ease of writing code

For example:

char character = `c`;    // binary stored in character is 0110 0011

unsigned char variable = character // will store 0110 0011 in variable

And pointers are just used to access the memory location of variables.

So when you Point to a char using a unsigned char*, only the way that data is interpreted is changed but the binary behind it is the same

Dhruv Vanjari
  • 122
  • 10
  • This is incorrect. When the standard allows implicit typecasting may change the underlying representation of the data as well. `int a=42; double b=a`. `b` will not be `0x2A`, but rather the IEEE 754 representation of the number closest to `42` – darnir Aug 17 '20 at 08:47
  • I was talking about `pointing to data`, not `casting` and storing it in another `variable`. Data stored in a memory location will be the same irrespective of the `data type` used to point to it. In my examples I have used `char` and `unsigned char`, and not `int` and `double`. – Dhruv Vanjari Aug 17 '20 at 08:59