Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allocating string with malloc

Tags:

c

string

malloc

I'm new in programming in C and now I'm studying strings. My question is: if I allocate a string using malloc (as in the code below), is the NULL character automatically inserted at the end of the string? I find an answer in another question here, and it seems that the NULL character is not automatically included. But here comes the problem: I know functions like strlen don't work if there isn't the NULL character, and in this code I use it and it works. So I think there is \0 at the end of my string, even if I don't write it anywhere. What's the answer?

Here's the code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char** argv) {
    char *stringa1;
    int n;
    int i;

    printf("How many characters in the string? ");
    scanf("%d", &n);

    stringa1 = (char*) malloc(n*sizeof(char));

    printf("Insert the string: ");
    scanf("%s", stringa1);

    free(stringa1);

    return 0;
}
like image 362
FranzGoogle Avatar asked Jan 24 '17 14:01

FranzGoogle


People also ask

Can we use malloc for string?

If we use static memory then either we have to face a shortage of memory or the memory will be free and of no use. We can take the input of strings from the user to create an array using the malloc() function and this is explained in detail in the article.

How do I allocate with malloc?

ptr = (cast-type*) malloc(byte-size) For Example: ptr = (int*) malloc(100 * sizeof(int)); Since the size of int is 4 bytes, this statement will allocate 400 bytes of memory. And, the pointer ptr holds the address of the first byte in the allocated memory.

What does malloc () calloc () realloc () free () do?

Functions malloc, calloc, realloc and free are used to allocate /deallocate memory on heap in C/C++ language. These functions should be used with great caution to avoid memory leaks and dangling pointers.

How do I allocate strings in CPP?

For example: #include <string> const char* func1() { const char* s = "this is a literal string"; return s; } string func2() { std::string s = "this is a literal string"; return s; } const char* func3() { std::string s = "this is a literal string"; return s.


2 Answers

malloc returns pointer to an uninitialized memory extent.

If you want that the memory extent would be initialized by zeroes then you can use another standard function calloc instead of malloc.

Take into account that usually such a question like this

printf("How many characters in the string? ");

imply that the terminating zero is not counted. So you have to allocate one more byte of memory. For example

stringa1 = ( char* )malloc( ( n + 1 ) *sizeof( char ) );

or

stringa1 = ( char* )calloc( n + 1, sizeof( char ) );

In the last case you may apply the function strlen which returns 0 because the memory extent is zero-initialized.

This call of scanf

scanf("%s", stringa1);

is unsafe. It is better to use fgets instead. For example

fgets( stringa1, n + 1, stdin );

This function can append the string with the new line character. To remove it from the string you can write

stringa1[strcspn( stringa1, "\n" )] = '\0';
like image 141
Vlad from Moscow Avatar answered Sep 20 '22 12:09

Vlad from Moscow


malloc() returns a void* pointer to a block of memory stored in the heap. Allocating with malloc() does not initialize any string, only space waiting to be occupied.To add a null-terminating character, you either have to do this yourself, or use a function like scanf(), which adds this character for you. Having said this, you need to allocate space for this \0 character beforehand.

Your malloc() call should be this instead:

stringa1 = (char*) malloc((n+1)*sizeof(char)); /*+1 for '\0' character */

Note: You don't need to cast return of malloc. For more information, read this.

Another thing to point out is sizeof(char) is 1, so multiplying this in your malloc() call is not necessary.

You also need to check if malloc() returns NULL. This can be done like this:

if (stringa1 == NULL) {
    /* handle exit */

Also, you can only use strlen() on a null-terminated string, otherwise this ends up being undefined behaviour.

Once scanf() is called, and the stringa1 contains some characters, you can call strlen() on it.

Additionally, checking return of scanf() is also a good idea. You can check it like this:

if (scanf("%d", &n) != 1) {
    /* handle exit */

Your code with these changes:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
    char *stringa1 = NULL;
    size_t n, slen;

    printf("How many characters in the string? ");
    if (scanf("%zu", &n) != 1) {
        printf("Invalid input\n");
        exit(EXIT_FAILURE);
    }

    stringa1 = malloc(n+1);
    if (stringa1 == NULL) {
        printf("Cannot allocate %zu bytes for string\n", n+1);
        exit(EXIT_FAILURE);
    }

    printf("Insert the string: ");
    scanf("%s", stringa1);

    slen = strlen(stringa1);
    printf("String: %s Length: %zu\n", stringa1, slen);

    free(stringa1);
    stringa1 = NULL;

    return 0;
}
like image 34
RoadRunner Avatar answered Sep 20 '22 12:09

RoadRunner