15

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;
}
Tony Tannous
  • 14,154
  • 10
  • 50
  • 86
FranzGoogle
  • 451
  • 3
  • 5
  • 14
  • 1
    Your code looks fine to me. `scanf` puts the NUL (not NULL) at the end of the string. Try calling `strlen` right before `free(stringa1)`. – Jabberwocky Jan 24 '17 at 14:19
  • 1
    To repeat what @MichaelWalz said, and to nitpick, a pointer can be `NULL` and a character can be `NUL`. – Fiddling Bits Jan 24 '17 at 14:26
  • In a previous version I tried and it returns the number I put in the first `scanf()`. – FranzGoogle Jan 24 '17 at 14:28
  • I see no real issue with your code, except for [casting the result of malloc](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). It has no particularly negative effect here but is considered bad practice and can hide errors. – George Jan 24 '17 at 14:32
  • There is no `NULL` character. `NULL` is a macro with a _null pointer constant_, something very different. And C does not have a string type. – too honest for this site Jan 24 '17 at 14:52

5 Answers5

25

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;
}
Community
  • 1
  • 1
RoadRunner
  • 25,803
  • 6
  • 42
  • 75
  • can we just to type the string and C automatically counts the length of the string and reserve the space needed for the char? how to achieve that? – Agung Sudrajat Feb 03 '22 at 05:02
8

if I allocate a string using malloc (as in the code below), is the NULL character automatically inserted at the end of the string?

No. malloc() returns a block of uninitialized memory.

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 wrote it nowhere.

scanf() inserts the null byte ('\0') for you when you use %s format specifier (assuming scanf() succeeded).

From man scanf():

s Matches a sequence of non-white-space characters; the next pointer must be a pointer to the initial element of a character array that is long enough to hold the input sequence and the terminating null byte ('\0'), which is added automatically. The input string stops at white space or at the maximum field width, whichever occurs first.

(emphasis mine).

By the way, you should do error checking for scanf() and malloc() calls.

P.P
  • 117,907
  • 20
  • 175
  • 238
  • 1
    And he should also be sure to include space for the trailing null byte in his allocation, and he should protect against the actual string fed as input to the program being longer than was promised. – John Bollinger Jan 24 '17 at 14:23
  • Thank you, but I can't understand when you talking about the error checking for `scanf()` and `malloc()`... – FranzGoogle Jan 24 '17 at 14:26
  • @FranzGoogle `scanf()` returns the number of items scanned successfully; otherwise, it's failed. `malloc()` returns a NULL if it's failed to allocate memory. So, what I was saying was you have to check the return code of those functions to check if they have failed. Such as: `if (scanf("%d", &n) != 1) { /* failure */}` and `stringa1 = (char*) malloc(n*sizeof(char)); if (stringa1 == NULL) { /* failure */}` etc. – P.P Jan 24 '17 at 14:28
  • @P.P. OK. And how can I do it? Sorry, but I'm a beginner... Can I check it with a `strlen()`? – FranzGoogle Jan 24 '17 at 14:33
  • @FranzGoogle See the end of my previous comment on how to do it. Not sure how `strlen()` is relevant. `strlen()` simply returns the length of the string (and `strlen()` *requires* a null byte terminated string as input). So, if `malloc()` failed then you can't call `strlen()` on `stringa1`. You should just check each function for its failure. – P.P Jan 24 '17 at 14:39
  • @P.P. I understand the first control for the `malloc()`, but I can't understand the second one... – FranzGoogle Jan 24 '17 at 14:54
  • @FranzGoogle Do you mean the error checking for `scanf()`? – P.P Jan 24 '17 at 14:56
  • `scanf()` returns how you *items* it scanned successfully. In `scanf("%d", &n)`, you asked to scan 1 item. So, it should return 1 on success. So, `if (scanf("%d", &n) != 1) { /* failure */}` is how you check it. Similarly, `if (scanf("%s", stringa1) != 1) { /* failure */}`. If you scan 2 items, for example: `int x, y; scanf("%d%d", &x, &y);` then you should check against 2. – P.P Jan 24 '17 at 15:01
  • @FranzGoogle You should probably read the documentation of the functions as well. That should be the first step if you don't know how a function works. You can always make more toy programs, try with different inputs etc. If you still don't understand the docs, then you can ask for clarifications. – P.P Jan 24 '17 at 15:15
2

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';
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

The definition of "string" in C is a sequence of characters, terminated by a null character.

To allocate memory for a string, count the chracters (e.g. strlen) and add 1 for this terminating null character.

Functions like scanf and strcpy add the null character; a function like strncpy doesn't always do that.

Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
0

The easy way to achieve this is to include cs50 library. Just use get_string function:

#include <stdio.h>
#include <cs50.h>

int main(void) {
    // input the string to stringa1
    char *stringa1 = get_string("Insert the string: ");

    // call the string
    printf("The string you type was: %s\n", stringa1);

    return 0;
}

Sample output: Insert the string: Hello World, I am newbie! The string you type was: Hello World, I am newbie!