When dynamically allocating char
s, I've always done it like this:
char *pCh = malloc(NUM_CHARS * sizeof(char));
I've recently been told, however, that using sizeof(char)
is redundant and unnecessary because, "by definition, the size of a char
is one byte," so I should/could write the above line like this:
char *pCh = malloc(NUM_CHARS);
My understanding is the size of a char depends on the native character set that is being used on the target computer. For example, if the native character set is ASCII, a char
is one byte (8 bits), and if the native character set is UNICODE a char
will necessarily require more bytes (> 8 bits).
To provide maximum portability, wouldn't it be necessary to use sizeof(char)
, as malloc
simply allocates 8-bit bytes? Am I misunderstanding malloc
and sizeof(char)
?
dynamically allocated arrays To dynamically allocate space, use calls to malloc passing in the total number of bytes to allocate (always use the sizeof to get the size of a specific type).
Yes, it is redundant since the language standard specifies that sizeof (char)
is 1. This is because that is the unit in which things are measured, so of course the size of the unit itself must be 1.
Life becomes strange with units defined in terms of themselves, that simply doesn't make any sense. Many people seem to "want" to assume that "there are 8-bit bytes, and sizeof
tells me how many such there are in a particular value". That is wrong, that's simply not how it works. It's true that there can be platforms with larger characters than 8 bits, that's why we have CHAR_BIT
.
Typically you always "know" when you're allocating characters anyway, but if you really want to include sizeof
, you should really consider making it use the pointer, instead:
char *pCh = malloc(NUM_CHARS * sizeof *pCh);
This "locks" the unit size of the thing being allocated the pointer that is used to store the result of the allocation. These two types should match, if you ever see code like this:
int *numbers = malloc(42 * sizeof (float));
that is a huge warning signal; by using the pointer from the left-hand side in the sizeof
you make that type of error impossible which I consider a big win:
int *numbers = malloc(42 * sizeof *numbers);
Also, it's likely that if you change the name of the pointer, the malloc()
won't compile which it would if you had the name of the (wrong) basic type in there. There is a slight risk that if you forget the asterisk (and write sizeof numbers
instead of sizeof *numbers
) you'll not get what you want. In practice (for me) this seems to never happen, since the asterisk is pretty well established as part of this pattern, to me.
Also, this usage relies on (and emphasizes) the fact that sizeof
is not a function, since no ()
s are needed around the pointer de-referencing expression. This is a nice bonus, since many people seem to want to deny this. :)
I find this pattern highly satisfying and recommend it to everyone.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With