PakyaBhai
PakyaBhai

Reputation: 23

Requirement of `malloc()` in this case

Right now, I am studying a Yale course.

One of the snippets is:

char *
strdup(const char *s)
{
    char *s2;

    s2 = malloc(strlen(s)+1);

    if(s2 != 0) {
        strcpy(s2, s);
    }

    return s2;
}

If I understand correctly, we need a malloc() here since we are copying the string s into another string s2 and so we need to allocate enough space to s2. However, when I tried out the following code:

#include <stdio.h>

int main(void) {
    // your code goes here
    char *str = "Test";

    printf("%s", str);

    return 0;
}

here, it gives me the correct and expected output.

So, I have two questions:

  1. Is malloc() needed in the first snippet because we need s2 to be an array?

  2. Am I invoking UB in the second snippet, (because I have no where declared *str to be pointing to an array)? And we need an array because in C, a string is stored as a character array.

Upvotes: 1

Views: 78

Answers (3)

user2736738
user2736738

Reputation: 30926

Yes it's needed to duplicate the string. (The reason you stated in irrelevant) You are allocating memory to hold the duplicated string. In the second case you are just printing the literal by passing a pointer to it to printf, you are not duplicating anything.

No UB here - this is legal code. char* str is initialzing the char* to the decayed pointer to the literal array. The decayed pointer points to the first element of the array.

Indeed a string is stored as char array in C - but how does it affect the behavior we just saw in the second snippet? We are passing a char* which points to the null terminated char array exactly what is being expected by the %s specifier of printf.

Also the literals are having static storage duration. You don't need to create memory for storing them. This is done implicitly when you have written "Test".

Upvotes: 2

Vlad from Moscow
Vlad from Moscow

Reputation: 310950

I have no where declared *str to be pointing to an array

You are mistaken. String literals stored as character arrays with the static storage duration.

So in this declaration

char *str = "Test";

two things occur.

The first one is the compiler creates a character array of the type char[5] where the string literal is stored. Then the address of the first character of the array is used to initialize the pointer str that has the automatic storage duration.

You can even rewrite the declaration the following way

char *str = &"Test"[0];

Is malloc() needed in the first snippet because we need s2 to be an array?

The function strdup creates a copy of the original string. So you have to store somewhere the created copy. To do this you have to allocate enough memory to store the copy and return from the function a pointer that will point to the allocated memory with the string copy.

Upvotes: 0

Eric Postpischil
Eric Postpischil

Reputation: 222372

This code:

char *str = "Test";

means:

  • Create an array of five characters containing T, e, s, t, and a null character. Storage for this array is “static”; it is allocated for the entire lifetime of your program.

  • Create a pointer to char named str and set its initial value to the address of the first character in that array created above.

In this case, the storage for "Test" is automatically allocated for you as part of compiling, loading, and executing your program.

In contrast, in the strdup code, the function is passed a pointer to a string. (A string is an array of characters that has a null character to mark the end of the string.) In this case, the function does not know in advance how long the string is. So it does not know how much memory it needs until the function is called and it uses strlen to measure the length of the string.

When you do not know in advance how much memory is needed, you generally need to use malloc or one of the related memory-allocation routines to allocate storage. (Another method is to use variable-length arrays. Not all C implementations support variable-length arrays, and they should be used only for small, or perhaps moderate size, arrays that are needed only within one function.)

Upvotes: 1

Related Questions