I was doing some C coding and after reading some C code I've noticed that there are code snippets like
char *foo = (char *)malloc(sizeof(char) * someDynamicAmount);
So I want to ask what's more C-ish way to allo开发者_运维百科cate memory for char array? Use sizeof(char)
and supposedly future-proof the code against any standard changes or omit it and use the number directly?
The more Cish way would be
char* foo = malloc(someDynamicAmount * sizeof *foo);
referencing the variable and not the type so that the type isn't needed. And without casting the result of malloc (which is C++ish).
I do sizeof(char)
to make the intentions clear. If anyone ever decides he wants foo to be an int
he knows he'll need to do sizeof(int)
for it to keep on working.
or omit it and use the number
Plus it's not very good coding practice to use magic numbers.
IMHO the best practice is to write sizeof(*foo)
. Then you're
covered also if the type of foo changes and the sizeof is not corrected.
Compare:
float*baz = malloc(sizeof(float) * someDynamicAmount);
int *bar = malloc(sizeof(int) * someDynamicAmount);
char *foo = malloc(sizeof(char) * someDynamicAmount);
Vs:
float*baz = malloc(sizeof(float) * someDynamicAmount);
int *bar = malloc(sizeof(int) * someDynamicAmount);
char *foo = malloc(someDynamicAmount);
I like the first version. Do you prefer the second?
You're correct, by standard, the multiplication is irrelivant. That said, it looks like a habit someone got into to be consistent. If you always use the sizeof()
, regardless of type, you never forget.
char *foo = (char *)malloc(sizeof(char) * someDynamicAmount);
int *bar = (int *)malloc(sizeof(int) * someDynamicAmount);
The common idiom is
T *p = malloc(N * sizeof *p);
or
T *p;
...
p = malloc(N * sizeof *p);
This way you don't have to worry about the type.
Citing C99 standard, section 6.5.3.4 The sizeof
operator:
When applied to an operand that has type char, unsigned char, or signed char, (or a qualified version thereof) the result is 1. When applied to an operand that has array type, the result is the total number of bytes in the array. When applied to an operand that has structure or union type, the result is the total number of bytes in such an object, including internal and trailing padding.
That is, sizeof char == 1
by the standard, not by the implementation. Therefore it is absolutely correct to omit sizeof(char)
when calling malloc()
for chars and in similar cases. IMHO, it is highly improbable that future C standard will allow implementation-specific size of char
, because too much code already depends on it to be 1 and backward compatibility is very important in C.
Therefore, the question is only about style, not correctness and here I support AProgrammer's answer.
Writing sizeof(char)
is not "future-proofing" your code against possible changes in the standard. It's usually a sign of complete misunderstanding of what sizeof
means and the whole fundamental model of memory objects in C - what's referred to as Representation of Types in the language of the C standard. The only reason a sizeof
operator even exists or makes sense is because C specifies objects to have a "representation" in memory in terms of a smallest possible unit that is unsigned char
. If not for this, storage would be a lot more abstract and there would be no use of sizeof
and the related pointer arithmetic.
sizeof
is defined in units of char
, i.e. sizeof(T)==N
means type T
occupies N
char
s. In light of this, sizeof(char)
is completely silly; it's attempting to measure how many char
s a char
occupies.
This is all a matter of coding style. Several styles exist.
To actually answer the question, people write
malloc(n * sizeof(char))
to keep all their code that uses malloc
consistent. Next time they might need int
and then they can write the code in the very same way,
malloc(n * sizeof(int))
So the reason why it is done to keep the coding style consistent. Even though sizeof(char)
is indeed guaranteed to always be 1 and is therefore superfluous. It is a way to write self-documenting code.
However, the most common way to use malloc in C is perhaps
type* t = malloc(n * sizeof(*t));
or 100% equivalent:
type* t = malloc(n * sizeof *t);
Since the operator of sizeof
is not evaluated for side-effects, this code is safe, even though the variable t
is not yet initialized.
The third possible style is the pedantically correct one, which would use array pointers, since what we allocate is actually arrays:
type (*t)[n] = malloc( sizeof(type[n]) );
This is perhaps the most correct way, as far as type correctness is concerned. The size of an array is allocated, and we point at the allocated array with an array pointer.
However, the problem with this style is that array pointers add extra complexity to the syntax: you would have to de-reference this array as (*t)[i]
instead of t[i]
. It makes the code harder to read. (And also as a side-note, if n is not an integer constant expression, the code won't compile on old, outdated C compilers.)
The coding style can also be written as :-
char *foo = (char *)malloc(1 * someDynamicAmount);
But this is done so that the dynamically allocating memory can be increased according to the no of basic data type one wants. if u wanna increase 100 char it will increase 100 char. If may not have need but if we write 101 or 102 doing that would waste memory. doing the it according to the basic data type would not waste any memory space
The standard is deliberately vague about the sizes of common types. [Wikipedia]
While it is unlikely that the size of a char
won't change, but the size of short
has changed. The idiomatic way is:
type_t *foo = malloc(sizeof(type_t) * someDynamicAmount);
for any type (common or complex) type_t or
type_t *foo = malloc(sizeof(*foo) * someDynamicAmount);
So that you can decide to make changes to the type of foo later on and only change it in one place.
Think of unicode and multi-byte strings. If char represents single character in a string, it can actually occupy more than one byte, resulting in sizeof() > 1
精彩评论