Re: fgets behaviour with strncmp



Richard Heathfield wrote:

santosh said:

Richard Heathfield wrote:

santosh said:

<snip>

In fact, would the cast to unsigned char be necessary at
all, given that all the characters returned by fgets are guaranteed
to be positive integers?

Chapter and verse, please. I think you're mistaken about the
existence of such a guarantee. It applies to fgetc, yes, but not to
fgets.

Aren't all the standard byte input functions implemented as if they
were composed of successive calls to fgetc?

Yes.

If so, a guarantee for fgetc
should be applicable to functions modelled upon it too.

And so it is - for just as long as you are storing the results in an
array of unsigned char. But you're not, are you? You're storing them
(quite properly) in an array of char. So, on systems where char is
signed by default (and there are still quite a few of those about),
you have a problem if you assume that they are representable as
unsigned char without a conversion taking place. For example, consider
an input to fgets that includes a character with code point 130, on a
system with 8-bit char, signed by default. The fgets function will
read this as if via fgetc, so the value 130 will be returned from
fgetc (or "as-if-fgetc" if you prefer) as an int. This fulfils the
terms of the contract that you mentioned. Now fgets has to store this
value somewhere in your array of char. Since, on the system I've
mentioned, CHAR_MAX is 127, fgets will have to store the 130 into that
array as a negative number: -126 is a definite possibility (I know
because it's what happens on my system!), and -126 is not
representable as unsigned char, because unsigned char can't represent
negative values unless they are first converted into non-negative
values.

In the case in point, the C99 function isblank is being used. This is
one of the "is*" functions, prototyped in <ctype.h>, that require
their input to be either EOF or a value representable as an unsigned
char. We have discussed many times before how negative values can foul
this up. For example:

#define isblank(x) ( ((x) == EOF) ? (x) : __isblank[(x)] )

which invokes undefined behaviour if passed a negative value other
than EOF. (E&OE - my track record on illustrative is* macros is
appalling.)

Okay, many thanks for making that clear.

.



Relevant Pages

  • Re: Any way to take a word as input from stdin ?
    ... Now here I am thinking of using fgets() to ... fgetsuses array top store data and I don't know how large ... so I can't decide on the size of the array. ... I mean the char that doesn't belong to the word and signifies ...
    (comp.lang.c)
  • Re: fgets behaviour with strncmp
    ... of such a guarantee. ... It applies to fgetc, yes, but not to fgets. ... And so it is - for just as long as you are storing the results in an array ... problem if you assume that they are representable as unsigned char without ...
    (comp.lang.c)
  • Re: gets() is dead
    ... That certainly means I am unable to use fgets() safely, ... char *readstr ... tmp = realloc; ... strcpy(input, buffer); ...
    (comp.lang.c)
  • Re: Is this string input function safe?
    ... return a pointer to mallocated memory holding one input string, ... See my comment after your call to fgets. ... char* malloc_getstr ... before any characters are read, then the ...
    (comp.lang.c)
  • Re: slurping in binary data
    ... Key point to keep in mind here: I was thinking of sscanf, not fscanf() ... How does fgets know to stop? ... 100000001111100 as the line number and put "13" into the data buffer; ... char pattern; ...
    (comp.lang.c)