newbie questions about malloc and sizeof

2019-01-03 18:03发布

Can someone explain to me why my call to malloc with a string size of 6 returns a sizeof of 4 bytes? In fact, any integer argument I give malloc I get a sizeof of 4. Next, I am trying to copy two strings. Why is my ouput of the copied string (NULL)? Following is my code:

int main()
{
    char * str = "string";
    char * copy = malloc(sizeof(str) + 1);
    printf("bytes allocated for copy: %d\n", sizeof(copy));
    while(*str != '\0'){
        *copy = *str;
        str++;
        copy++;
    }
    copy = '\0';
    printf("%s\n", copy);
}

标签: c malloc sizeof
8条回答
唯我独甜
2楼-- · 2019-01-03 18:37

sizeof(str) returns the space necessary to store the pointer to the string, not the string itself. You can see the size of the string with strlen(str) for example.

Then you affect your copy pointer to an integer which has the value 0 (the character '\0'). It is the same as copy = NULL, which is what the printf() function shows you.

查看更多
唯我独甜
3楼-- · 2019-01-03 18:38

First you should understand that sizeof(xxx) where xxx is any left value expression (a variable) is always equivalent to do sizeof(type of xxx). Hence what is really doing your sizeof(str) is returning the size of a char *, that is the size of any other pointer. On a 32 bits architecture you'll get 4, on a 64 bits architecture it'll be 8, etc.

So, as others also explained you have to know the length of the string you want to allocate, and then add 1 to store the terminal \0, C implicitly use to put at the end of strings.

But to do what you want (copy a string and allocate necessary space) it will be more simple and more efficient to use strdup, that does exactly that : a malloc and a strcopy.

You should also not forget to free space you allocated yourself (using malloc, calloc, strdup or any other allocation function). In C it won't go away when allocated variable go out of scope. It will stay used until the end of the program. That's what you call a memory leak.

#include <string.h> /* for strdup, strlen */
#include <stdio.h> /* for printf */

int main()
{
    char * str = "string";
    char * copy = strdup(str);
    printf("bytes at least allocated for copy: %d\n", strlen(copy)+1);
    printf("%s\n", copy);
    free(copy);
}

One last point : I changed message to bytes at least allocated because you don't really know the size allocated when calling malloc. It quite often allocates a slighly more space that what you asked for. One reason is that in many memory managers free blocks are linked together using some hidden data structure and any allocated block should be able to contain at least such structure, another is that allocated blocks are always aligned in such a way to be compatible with any type alignment.

Hope it will help you to understand C a little better.

查看更多
【Aperson】
4楼-- · 2019-01-03 18:38

sizeof() returns the size of the actual type of the variable. So, when you define your type as char *, it returns the size of a pointer.

But if you made your variable an array, sizeof would return the size of the array itself, which would do what you want to do:

char *ptr = "moo to you";
char arr[] = "moo to you";

assert(sizeof(ptr) == 4);   // assuming 32 bit
assert(sizeof(arr) == 11);  // sizeof array includes terminating NUL
assert(strlen(arr) == 10);  // strlen does not include terminating NUL
查看更多
祖国的老花朵
5楼-- · 2019-01-03 18:40

You can use:

size_t malloc_usable_size (void *ptr);

instead of : sizeof

But it returns the real size of the allocated memory block! Not the size you passed to malloc!

查看更多
劫难
6楼-- · 2019-01-03 18:46

sizeof(str) returns the size of a pointer of type char*. What you should do is to malloc the size of the string it self:

char * copy = malloc(strlen(str) + 1);

Also, these lines:

while(*str != '\0'){
        *copy = *str;
        str++;
        copy++;
}
copy = '\0';

Can be rewritten easily in C like this:

while(*copy++ = *str++);
查看更多
孤傲高冷的网名
7楼-- · 2019-01-03 18:51

To tackle your second questions, by executing the statement copy++ you have changed the value of copy (that is, the address in memory that holds a char array) so that by the time you print it out, it is pointing at the end of the array rather than the beginning (the value returned by malloc()). You will need an extra variable to update the string and be able to access the beginning of the string:

Edit to repair malloc/sizeof issue - thanks CL.

char * str = "string";
/*   char * copy = malloc(sizeof(str) + 1);  Oops  */
char * copy = malloc(strlen(str) + 1);
char * original_copy = copy;
printf("bytes allocated for copy: %d\n", sizeof(copy));
while(*str != '\0'){
    *copy = *str;
    str++;
    copy++;
}
copy = '\0';
printf("%s\n", original_copy);
查看更多
登录 后发表回答