Search code examples
cpointersscanfimplicit-conversionc-strings

Defining strings using pointers Vs. char arrays in C


I am confused about how pointers to characters work. when I run the following code, what happens?

int main()
{
    char* word;
    scanf("%s",word);
    printf("%s",word;
}

the first line in the main is defining a pointer to char without initialization. scanf should store the word somewhere and give the address to the pointer, right? what if I input a big string, would it overwrite something in the memory?

And what happens in the first line in the following code other than defining a pointer to char. Does the compiler set some limits? or I can't exceed the size specified, right? If done, I will have a run time error, right? what is the difference between the two cases?

int main()
{
    char word[100];
    scanf("%s",word);
    printf("%s",word;
}

What about pointers to other types? Can I just keep writing to the following places using offsets?


Solution

  • The function scanf requires that you pass it the address of a sufficiently large memory buffer for storing the string. If you don't do this, then you will be invoking undefined behavior (i.e. your program may crash).

    Simply passing a wild pointer (i.e. an arbitrary memory address) is not sufficient. Rather, you must reserve the memory that you intend to use, for example by declaring an array or by using the function malloc.

    Using the %s scanf conversion format specifier by itself is not a good idea, because even if the allocated memory buffer has a size of 100 characters, if the user types more than 99 characters (100 including the terminating null character), then the function will write to the array out of bounds, causing undefined behavior. Therefore, you should always limit the number of characters that are written, in this case by writing %99s instead of simply %s.

    Also, before using the result of scanf, you should always check the return value of the function, and only use the result if the function was successful.

    int main()
    {
        char word[100];
        if ( scanf( "%99s", word ) == 1 )
            printf( "%s\n", word );
        else
            printf( "input error!\n" );
    }
    

    what if I input a big string, would it overwrite something in the memory?

    It doesn't have to be a "big" string. Writing even a "small" string to a wild pointer will cause undefined behavior and something important may be overwritten, or your program may crash.

    And what happens in the first line in the following code other than defining a pointer to char. Does the compiler set some limits?

    The line

    char word[100];
    

    will allocate an array of 100 characters, i.e. it will give you a memory buffer that is sufficiently large to store 100 characters. This does not give you a pointer. However, when using the array word in the line

    scanf("%s",word);
    

    the array word will decay to a pointer to the first element.

    Does the compiler set some limits? or I can't exceed the size specified, right?

    The compiler won't prevent you from writing to the array out of bounds, but if you allow this to happen, then your program will have undefined behavior (i.e. your program may crash). Therefore, you probably don't want to allow that to happen.

    If done, I will have a run time error, right?

    If you are lucky, then yes, your program will crash immediately and you will easily be able to identify and fix the bug. If you are unlucky, then no, your program won't crash, but will work as intended, and you won't notice the bug for a very long time, until much later in development, when one day the bug starts overwriting something important in your program. In that case, the bug will probably be hard to diagnose.

    This is because C is not a memory-safe language.

    However, because these kinds of bugs are often hard to find, there are tools which can help detect these kinds of bugs, such as valgrind and AddressSanitizer.