HelloWorld
HelloWorld

Reputation: 21

Why char * c = NULL; causes an error in the following code?

My understanding:

Can anyone please enlighten me why and how char * c = NULL; is causing an error?

Thanks in advance!

#include <stdio.h>

int main(void)
{
    char * c = NULL;
    gets(c);
    printf("%c, %c\n", c[0], c[1]);
    return 0;

}

Upvotes: 1

Views: 757

Answers (2)

David C. Rankin
David C. Rankin

Reputation: 84541

char *c = NULL; declares the pointer c initialized to NULL. It is a pointer to nowhere.

Recall, A pointer is just a variable that holds the address to something else as its value. Where you normally think of a variable holding an immediate values, such as int a = 5;, a pointer would simply hold the address where 5 is stored in memory, e.g. int *b = &a;. Before you can use a pointer to cause data to be stored in memory -- the pointer must hold the address for (e.g. it must point to) the beginning of a valid block of memory that you have access to.

You can either provide that valid block of memory by assigning the address of an array to your pointer (where the pointer points to where the array is stored on the stack), or you can allocate a block of memory (using malloc, calloc or realloc) and assign the beginning address for that block to your pointer. (don't forget to free() what you allocate).

The simplest way is to declare a character array and then assign the address to the first element to your pointer (an array is converted to a pointer to the first element on access, so simply assigning the character array to your pointer is fine). For example with the array buf providing the storage and the pointer p holding the address of the first character in buf, you could do:

#include <stdio.h>
#include <string.h>     /* for strcspn & strlen */

#define MAXC 1024       /* if you need a constant, #define one (or more) */

int main (void)
{
    char buf[MAXC],                         /* an array of MAXC chars */
        *p = buf;                           /* a pointer to buf */

    if (fgets (p, MAXC, stdin)) {           /* read line from stdin */
        p[strcspn (p, "\n")] = 0;           /* trim \n by overwriting with 0 */
        if (strlen (p) > 1) {               /* validate at least 2-chars */
            printf("%c, %c\n", p[0], p[1]); /* output them */
        }
    }

    return 0;
}

(note: strcspn above simply returns the number of character in your string up to the '\n' character allowing you to simply overwrite the '\n' included by fgets() with '\0' -- which is numerically equivalent to 0)

Example Use/Output

$ ./bin/fgetsmin
Hello
H, e

Look things over and let me know if you have further questions.

Upvotes: 1

ShadowRanger
ShadowRanger

Reputation: 155363

gets doesn't allocate memory. Your pointer is pointing to NULL, which cannot be written to, so when gets tries to write the first character there, you seg fault.

The solution is:

  1. Use a stack or global array (char c[1000];) or a pointer to dynamically allocated memory (char *c = malloc(1000);), not a NULL pointer.
  2. Never use gets, which is intrinsically broken/insecure (it can't limit the read to match the size of the available buffer); use fgets instead.

Upvotes: 1

Related Questions