简体   繁体   中英

C memory allocating - char* and char sizeof

What form is correct in allocating string in C?

char *sample;

sample = malloc ( length * sizeof(char) );

or

sample = malloc ( length * sizeof(char*) );

Why does char* take 4 bytes when char takes 1 byte?

Assuming the goal is to store a string of length characters, the correct allocation is:

sample = malloc(length + 1);

Notes:

  1. Don't use sizeof (char) , since it's always 1 it doesn't add any value.
  2. Remember the terminator, I assumed (based on name) that length is the length in visible characters of the string, ie the return of strlen() will be length .
  3. I know you didn't, but it's worth pointing out that there should be no cast of the return value from malloc() , either.

The reason char * is larger is that it's a pointer type, and pointers are almost always larger than a single character. On many systems (such as yours, it seems) they are 32 bit, while characters are just 8 bits. The larger size is needed since the pointer needs to be able to represent any address in the machine's memory. On 64-bit computers, pointers are often 64 bits, ie 8 characters.

Why does char* take 4 bytes when char takes 1 byte?

Because you are on a 32-bit systems, meaning that pointers take four bytes; char* is a pointer.

char always takes exactly one byte, so you do not need to multiply by sizeof(char) :

sample = malloc (length);

I am assuming that length is already padded for null termination.

sample = malloc(length);

is the right one

char* is a pointer, a pointer uses 4 bytes (say on a 32-bit platform)

char is a char, a char uses 1 byte

sample = malloc ( length * sizeof(char) );

First is the correct one if you want to allocate memory for length number of characters.

char* is of type pointer which happens to be 4 bytes on your platform. So sizeof(char*) returns 4.

But sizeof(char) is always 1 and smae is guaranteed by the C standard.

In the given cases you are doing two different things:

In the first case : sample = malloc ( length * sizeof(char) );

You are allocating length multiplied by the size of type char which is 1 byte

While in the second case : sample = malloc ( length * sizeof(char*) );

You are allocating length multiplied by the size of pointer to char which is 4 byte on your machine.

Consider that while case 1 remains immutable, on the second case the size is variable.

In your case, you want to alloc an array of length characters. You will store in sample a pointer to an array of length times the size of what you point to. The sizeof(char*) is the size of a pointer to char . Not the size of a char .

A good practice is

sample = malloc(length * sizeof(*sample));

Using that, you will reserve length time the size of what you want to point to. This gives you the ability to change the data type anytime, simply declaring sample to be another kind of data.

int *sample;

sample = malloc(length * sizeof(*sample)); // length * 4


char *sample;

sample = malloc(length * sizeof(*sample)); // length * 1

Provided the length already accounts for the nul terminator, I would write either:

sample = malloc(length);

or:

sample = malloc(length * sizeof(*sample));

sizeof(char*) is the size of the pointer, and it is completely irrelevant to the the size that the allocated buffer needs to be. So definitely don't use that.

My first snippet is IMO good enough for string-manipulation code. C programmers know that memory and string lengths in C are both measured in multiples of sizeof(char) . There's no real need to put a conversion factor in there that everybody knows is always 1 .

My second snippet is the One True Way to write allocations in general. So if you want all your allocations to look consistent, then string allocations should use it too. I can think of two possible reasons to make all your allocations look consistent (both fairly weak IMO, but not actually wrong):

  • some people will find it easier to read them that way, only one visual pattern to recognise.
  • you might want to use the code in future as the basis for code that handles wide strings, and a consistent form would remind you to get the allocation right when the length is no longer measured in bytes but in wide chars. Using sizeof(*sample) as the consistent form means you don't need to change that line of code at all, assuming that you update the type of sample at the same time as the units in which length is measured.

Other options include:

sample = calloc(length, 1);
sample = calloc(length, sizeof(char));
sample = calloc(length, sizeof(*sample));

They're probably fairly pointless here, but as well as the trifling secondary effect of zeroing the memory, calloc has an interesting difference from malloc that it explicitly separates the number and size of objects that you're planning to use, whereas malloc just wants the total size.

For any type T , the usual form is

T *p = malloc(N * sizeof *p);

or

T *p;
...
p = malloc(N * sizeof *p);

where N is the number of elements of type T you wish to allocate. The expression *p has type T , so sizeof *p is equivalent to sizeof (T) .

Note that sizeof is an operator like & or * , not a library function; parentheses are only necessary if the operand is a type name like int or char * .

Please visit this Link https://www.codesdope.com/c-dynamic-memory/ for understand how it allocat the memory dynamically at run time. It might be helpful to understand the concept of malloc and how it allocate the amount of memory to the variable.

In your example;

char *sample;
sample = malloc ( length * sizeof(char) );

here, you are declare a pointer to character for sample without declaring how much memory it required. In the next line, length * sizeof(char) bytes memory is assigned for the address of sample and (char*) is to typecast the pointer returned by the malloc to character.

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