0

So, I came across the answer below on StackOverflow

fgets is not actually deprecated in C99 or the current standard, C11. But the author of that tutorial is right that fgets will not stop when it encounters a NUL and has no mechanism for reporting its reading of such a character.

The fgets function reads at most one less than the number of characters specified by n from the stream pointed to by stream into the array pointed to by s. No additional characters are read after a new-line character (which is retained) or after end-of-file.

What does it mean by "fgets will not stop if it encounters a NUL? Please explain with a simple code snippet.

Link: Why is the fgets function deprecated?

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • 1
    Show us the post. – anastaciu May 06 '20 at 20:12
  • 1
    What is so unclear about that remark? Say the input contains the following bytes: `41 41 41 41 00 4a 4b 4c 4d 10 4e 4f` How many bytes do you think `fgets` reads? – Cheatah May 06 '20 at 20:17
  • 1
    I guess the confusion is that `NULL` is not the same that `\0` character in C – Eugene Sh. May 06 '20 at 20:26
  • `fgets()` reads a line until a `'\n'` is found, so if the data contains a NUL character it will terminate the string and printing it all the substring between the NUL and the `\0` will "not appear without any clue of it. **BUT** fgets is designed to read text, and a nul character would be unexpected. So, saying that fgets is deprecated for this reason is just like saying that `strcpy` is unsafe because it will not copy data in a buffer if it contains string terminator characters. – Roberto Caboni May 06 '20 at 20:37
  • Niraj Raut, "when it encounters a NULL" confuses as `NULL` is the _null pointer constant_. Better to use _null character_ or `'\0'`. – chux - Reinstate Monica May 06 '20 at 21:04
  • @chux-ReinstateMonica NUL is the ASCII 0. NULL is the pointer 0. – stark May 07 '20 at 16:56
  • @stark Concerning [NULL is the pointer 0](https://stackoverflow.com/questions/61644485/what-does-it-mean-by-fgets-will-not-stop-if-it-encounters-a-nul?noredirect=1#comment109073666_61644485). C spec defines `NULL` as a _null pointer constant_ and has "An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant". `NULL` may be a non-pointer.such as `int 0` It might be the pointer 0. It is an implementation detail. – chux - Reinstate Monica May 07 '20 at 17:05
  • @chux-ReinstateMonica Yes. And the ASCII spec defines NUL as the character 0. You seem confused beteen 1 and 2 Ls – stark May 07 '20 at 17:14
  • @stark No confusion. My comments have not used `NUL` at all here - that is an ASCII definition. C calls it the _null character_ or `'\0'` as do my comments. – chux - Reinstate Monica May 07 '20 at 17:24
  • @stark I think the seeming confusion comes from Niraj Raut deleted comment that used `NULL` and the question originally did too. I edited the question from `NULL` to `NUL` 20 hours ago. Thus my comment about `NULL` refers to that missing comment and not a mis-read of the question in its present state. – chux - Reinstate Monica May 07 '20 at 17:33

2 Answers2

0

By convention, strings in C are "NUL-terminated". This means that the end of strings are determined by the presence of a "NUL" character. The NUL character is the character '\0' or more specifically a char with a value of 0. All C string literals are NUL-terminated, and most C APIs that take strings (both in the standard library and in most other libraries written in C) expect those strings to be NUL terminated.

This also means that a NUL character cannot be used as a normal data value in APIs that expect NUL terminations. Those APIs will treat the NUL character, not as a meaningful part of the string's data, but as the end of the string. For example, strlen("foo\0bar") is 3, not 7.

fgets reads character data from a file stream. But that file can contain NUL characters. What that post is saying is that fgets will treat NUL characters in the file exactly like any other character. fgets does NUL-terminate the string it is given, but if the file contains NUL characters, fgets will dutifully read them.

This is what the post is warning about: fgets does not treat NUL characters differently from any other character, while most other C API functions do. So if you pass a string generated by fgets to some API that expects NUL-termination, you may have a problem if that file contained NUL characters.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
0

Fgets is only intended for use with text files. Why would there be a null in a text file? So for most uses it is perfectly fine. At worst, you don't get to see the content after the null character, or you concatenate the next line into it because you think it is an incomplete line.

If you want to detect your fget()ed buffer contains nulls, prefill it with say chr 1, then look after the null to see if the chr1 has been overwritten. Or use ftell to see if more content has been read than your buffer size says. Remember that on windows this count can be off by 1 due to line ending translation, but if you think the text does /not/ contain a line-end up to the null then that is not an issue, really.

Gem Taylor
  • 5,381
  • 1
  • 9
  • 27
  • A common reason to find a _null character_, as a single byte, is in a text file that uses UTF16 encoding. Of course reading that text file with `fgets()` is not the best tool. Yet easy enough for a user to supply such a file. When reading in the proper 16/32 bit chunks, finding a 16-bit _null character_ would remain unusual. – chux - Reinstate Monica May 06 '20 at 21:00