0

below is the implementation of library function gets()

// I know gets() can cause buffer overflow easily, just use this fuction for demo purpose

char *gets(char *s)
{
   int c;
   char *dest = s;

   while ((c = getchar()) != ’\n’ && c != EOF)
      *dest++ = c;
   if (c == EOF && dest == s)
      return NULL;
   *dest++ = ’\0’;
   return s;
}

void echo()
{
   char buf[8];
   gets(buf);
}

I have two questions:

Q1-for this statement *dest++ = c;, we know that postfix increment has a higher precedence than dereference, so *dest++ is equivalent to *(dest++), but isn't that we lose the first element buf[0]?

Q2-why the gets() need to return a char pointer? isn't the return pointer the same as the argument s? isn't it more straightforward to make gets() method signature as:

void gets(char *s)
  • The return value of `gets()` is useful for error checking. See [this question](https://stackoverflow.com/q/21679063/4996248) for details. – John Coleman Jul 21 '20 at 00:55
  • @JohnColeman the argument is the same pointer as the returned pointer, users should check argument pointer to see if it is null for error checking –  Jul 21 '20 at 01:05
  • There is `return NULL`, but `s` is never set to `NULL` – Jorengarenar Jul 21 '20 at 01:11
  • I'm glad to see the comment about buffer overflow, but I'll still mention that the `gets` function has been removed from the C library as of the 2011 ISO C standard. – Keith Thompson Jul 21 '20 at 01:12

2 Answers2

2

Q1-for this statement *dest++ = c;, we know that postfix increment has a higher precedence than dereference, so *dest++ is equivalent to *(dest++), but isn't that we lose the first element buf[0]?

No, because post-increment returns the old value of the variable, not the incremented value. So we dereference the original dest value, then we increment it. It's equivalent to

*dest = c;
dest++;

You would be correct if it were *(++dest) = c;

Q2-why the gets() need to return a char pointer? isn't the return pointer the same as the argument s? isn't it more straightforward to make gets() method signature as:

The return value can be used to tell if there was an error. It returns NULL if there was an error.

It could have been designed to return an integer status. But the designers felt that it would be more useful if the return value were more meaningful than just this.

Many C string functions are similarly redundant. For instance, strcat() and strcpy() both return the destination string pointer.

Barmar
  • 741,623
  • 53
  • 500
  • 612
1

Q1-for this statement *dest++ = c;, we know that postfix increment has a higher precedence than dereference, so *dest++ is equivalent to *(dest++), but isn't that we lose the first element buf[0]?

The operation dest++ will return the value of dest before the operation

Q2-why the gets() need to return a char pointer? isn't the return pointer the same as the argument s? isn't it more straightforward to make gets() method signature as:

You could, but then you lose the information that the return value gives. If a NULL pointer is returned, then you know that something has happened.

klutt
  • 30,332
  • 17
  • 55
  • 95
  • for Q2, well isn't it more appropriate for users to check if the argument is null before passing it to `gets()`. –  Jul 21 '20 at 01:00