0

Why don't you need to specify the array size when using a pointer?

I'm new to C and trying to get a better understanding of how it works.

If I use a pointer to declare the array greet I don't need to specify the array size. If I take away the pointer I then need to define the size of the array.

Why does the compiler not need to know the size of the array to allocate when using a pointer to declare a char variable, but it does when I just declare a char variable. Bit confused on why this happens.

Here's my example code:

int main()
{
    char *greet; // Works fine.

    // char greet; // Doesn't work. Crashes when entering text.
    // char greet[]; // Doesn't work. Array size missing, won't compile.
    // char greet[20]; // Works fine.

    printf("Enter name\n>");
    gets(greet);

    printf("Hello %s", greet);


}
gsamaras
  • 71,951
  • 46
  • 188
  • 305
Brian16446
  • 149
  • 1
  • 13
  • 2
    "If I use a pointer to declare the array greet" - no, a pointer is not an array, you didn't "declare the array" there. You created a variable which can point to something (i.e. hold an address), and it doesn't point to anything meaningful right now. – vgru Sep 12 '17 at 09:41

2 Answers2

8

It seems to work fine, actually, it's undefined behavior.

For any uninitialized local variable of automatic storage type, if not initialized explicitly, the content is indeterminate. same is the case for greet in your code.

So, basically, you're trying to write into a memory for which the validity is unknown. The memory location, pointed to by greet is invalid, at best. You must make sure that the pointer you are using as the destination buffer points to some valid memory location. You can do this by either of below ways

  1. making the pointer point to valid memory location,

    char *greet = NULL;
    char buf[BUFSIZ] = {0};
    greet = buf;
    
    .
    .
    .
    
    fgets(greet, BUFSIZ, stdin);
    
  2. Allocate memory (at run-time) using dynamic memory allocator, like

    char * greet = malloc(BUFSIZ);
    
    if (greet) {// allocation successful....}
    

    and in this case, you need to take care of the clean-up also.

That said, DO NOT use gets(), it is dangerous (and removed from latest standard, AFAIR). Use fgets() instead.


As a side not, for the other options you mentioned,

  • char greet; is also invalid, fgets() (yes, even gets()) expected a pointer to char, not a char type. Enable warnings, and your compiler will scream. You better stop there!!

  • char greet[]; invalid syntax, altotger, nothing to discuss.

  • char greet[20]; this is right, as long as you pass a size that is less than / equal to the array size, in fgets(). This is OK because,

    • here, greet is an automatic local variable, so storage will be allocated automatically
    • the array name, while passed as function argument, decays to a pointer to the first element in the array

    and you'll be accssisng valid memory within the bounds. All good.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
6

A pointer is not an array. You have declared a pointer, but you allocate no space for where the pointer should point to (we dynamically allocate memory via malloc()), thus when you attempt to write to greet, you invoke Undefined Behavior, that's why it might seem to work fine on your machine, now, but it's not!

On the other hand char greet[20]; will work, because it's an array with size 20, ready to hold a string.

Moreover, consider using fgets() over gets(). Difference between fgets and gets.

Putting everything together, we could get:

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

int main(void)
{
    char *greet = malloc(21); // can hold a string of 20 characters, plus NULL terminator
    // TODO: Check for malloc failure

    printf("Enter name>\n");
    fgets(greet, 21, stdin);

    printf("Hello %s", greet);

    // Never forget to deallocate your dynamic memory!
    free(greet);
    return 0;
}

By using a fixed-size array, the code would look like this instead:

char greet[21];
printf("Enter name>\n");
fgets(greet, 21, stdin);
printf("Hello %s", greet);
gsamaras
  • 71,951
  • 46
  • 188
  • 305