getc and "large" bytes

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • vippstar@gmail.com

    #1

    getc and "large" bytes

    Assuming all the values of int are in the range of unsigned char, what
    happends if getc returns EOF?
    Is it possible that EOF was the value of the byte read?
    Does that mean that code aiming for maximum portability needs to check
    for both feof() and ferror()?
    (for example, if both feof() and ferror() return 0 for the stream when
    getc() returned EOF, consider EOF a valid byte read)
    To me, that seems to be the case, but maybe the standard says this to
    be incorrect.

    As always, all replies appreciated.
  • Ben Pfaff

    #2
    Re: getc and "large&quo t; bytes

    vippstar@gmail. com writes:
    Assuming all the values of int are in the range of unsigned char, what
    happends if getc returns EOF?
    Your assumption is false.
    --
    Ben Pfaff

    Comment

    • vippstar@gmail.com

      #3
      Re: getc and "large&quo t; bytes

      On May 23, 6:35 pm, Ben Pfaff <b...@cs.stanfo rd.eduwrote:
      vipps...@gmail. com writes:
      Assuming all the values of int are in the range of unsigned char, what
      happends if getc returns EOF?
      >
      Your assumption is false.
      Would you please elaborate?

      Comment

      • Richard Heathfield

        #4
        Re: getc and &quot;large&quo t; bytes

        vippstar@gmail. com said:
        On May 23, 6:35 pm, Ben Pfaff <b...@cs.stanfo rd.eduwrote:
        >vipps...@gmail .com writes:
        Assuming all the values of int are in the range of unsigned char, what
        happends if getc returns EOF?
        >>
        >Your assumption is false.
        Would you please elaborate?
        The int type must be able to represent values in the range INT_MIN to -1,
        none of which values are in the range of unsigned char (which, lacking a
        sign bit, cannot represent negative values).

        --
        Richard Heathfield <http://www.cpax.org.uk >
        Email: -http://www. +rjh@
        Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
        "Usenet is a strange place" - dmr 29 July 1999

        Comment

        • vippstar@gmail.com

          #5
          Re: getc and &quot;large&quo t; bytes

          On May 23, 6:42 pm, Richard Heathfield <r...@see.sig.i nvalidwrote:
          vipps...@gmail. com said:
          >
          On May 23, 6:35 pm, Ben Pfaff <b...@cs.stanfo rd.eduwrote:
          vipps...@gmail. com writes:
          Assuming all the values of int are in the range of unsigned char, what
          happends if getc returns EOF?
          >
          Your assumption is false.
          Would you please elaborate?
          >
          The int type must be able to represent values in the range INT_MIN to -1,
          none of which values are in the range of unsigned char (which, lacking a
          sign bit, cannot represent negative values).
          I'm talking about the case that both int and unsigned char are 16
          bits, and to be honest I'm still not convinced that this is false.

          Comment

          • Richard Tobin

            #6
            Re: getc and &quot;large&quo t; bytes

            In article <c9241d9e-3b73-450e-a012-5a5ab6f204f0@e3 9g2000hsf.googl egroups.com>,
            <vippstar@gmail .comwrote:
            >Assuming all the values of int are in the range of unsigned char, what
            >happends if getc returns EOF?
            If int and char are the same size, and all possible unsigned char
            values can be read, then it is possible that getc() will attempt to
            convert to an int a value which cannot be represented as one. This is
            implementation-defined. Assuming it works in the usual way, it may
            return a negative integer equal to EOF.
            >Does that mean that code aiming for maximum portability needs to check
            >for both feof() and ferror()?
            Yes, but it seems to me that undefined behaviour is involved.

            For maximum portability, don't use machines like that :-)

            -- Richard
            --
            In the selection of the two characters immediately succeeding the numeral 9,
            consideration shall be given to their replacement by the graphics 10 and 11 to
            facilitate the adoption of the code in the sterling monetary area. (X3.4-1963)

            Comment

            • Eric Sosman

              #7
              Re: getc and &quot;large&quo t; bytes

              vippstar@gmail. com wrote:
              On May 23, 6:42 pm, Richard Heathfield <r...@see.sig.i nvalidwrote:
              >vipps...@gmail .com said:
              >>
              >>On May 23, 6:35 pm, Ben Pfaff <b...@cs.stanfo rd.eduwrote:
              >>>vipps...@gma il.com writes:
              >>>>Assuming all the values of int are in the range of unsigned char, what
              >>>>happends if getc returns EOF?
              >>>Your assumption is false.
              >>Would you please elaborate?
              >The int type must be able to represent values in the range INT_MIN to -1,
              >none of which values are in the range of unsigned char (which, lacking a
              >sign bit, cannot represent negative values).
              I'm talking about the case that both int and unsigned char are 16
              bits, and to be honest I'm still not convinced that this is false.
              Then you didn't express quite what you meant.

              It seems to me that the behavior required of getc() places
              far-reaching requirements on implementations where `int' and
              `char' have the same width. Here are a few:

              1) Since `unsigned char' can represent 2**N distinct values
              and all of these must be distinguishable when converted to `int',
              it follows that `int' must also have 2**N distinct values. Thus,
              signed-magnitude and ones' complement representations are ruled
              out, and INT_MIN must have its most negative possible value
              (that is, INT_MIN == -INT_MAX - 1, all-bits-set cannot be a trap
              representation) .

              1a) "Must be distinguishable when converted" follows from
              7.19.2p3's promise that data read from a binary stream must
              compare equal to the data written. If two different characters
              mapped to the same `int', this promise couldn't be kept.

              2) Converting a too-large `unsigned char' to `int' must
              not raise a signal. (At least, it must not do so when getc()
              performs the conversion; it's possible that an "open-code"
              conversion would behave differently.)

              An implication of (1) for the programmer is that yes, there
              will be a legitimate `unsigned char' value that maps to EOF
              when converted to `int'. Hence, a maximally portable program
              cannot assume that the value EOF indicates a getc() failure;
              it must go on to check both feof() and ferror():

              int ch = getc(stream);
              if (ch == EOF) {
              if (feof(stream))
              return ALL_DONE;
              if (ferror(stream) )
              return ALL_FU;
              }
              return ALLS_WELL; /* even if ch == EOF */

              --
              Eric.Sosman@sun .com

              Comment

              • Ben Pfaff

                #8
                Re: getc and &quot;large&quo t; bytes

                vippstar@gmail. com writes:
                On May 23, 6:35 pm, Ben Pfaff <b...@cs.stanfo rd.eduwrote:
                >vipps...@gmail .com writes:
                Assuming all the values of int are in the range of unsigned char, what
                happends if getc returns EOF?
                >>
                >Your assumption is false.
                Would you please elaborate?
                -1 is in the range of int.
                -1 is not in the range of unsigned char.
                Therefore it is not true that all the values of int are in the
                range of unsigned char.
                --
                char a[]="\n .CJacehknorstu" ;int putchar(int);in t main(void){unsi gned long b[]
                ={0x67dffdff,0x 9aa9aa6a,0xa77f fda9,0x7da6aa6a ,0xa67f6aaa,0xa a9aa9f6,0x11f6} ,*p
                =b,i=24;for(;p+ =!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
                2:{i++;if(i)bre ak;else default:continu e;if(0)case 1:putchar(a[i&15]);break;}}}

                Comment

                • Bartc

                  #9
                  Re: getc and &quot;large&quo t; bytes


                  "Ben Pfaff" <blp@cs.stanfor d.eduwrote in message
                  news:87y7617zqb .fsf@blp.benpfa ff.org...
                  vippstar@gmail. com writes:
                  >
                  >On May 23, 6:35 pm, Ben Pfaff <b...@cs.stanfo rd.eduwrote:
                  >>vipps...@gmai l.com writes:
                  >Assuming all the values of int are in the range of unsigned char, what
                  >happends if getc returns EOF?
                  >>>
                  >>Your assumption is false.
                  >Would you please elaborate?
                  >
                  -1 is in the range of int.
                  -1 is not in the range of unsigned char.
                  Therefore it is not true that all the values of int are in the
                  range of unsigned char.
                  The OP mentioned an example where both might be 16 bits. So -1 in one could
                  be 0xFFFF in the other, causing ambiguity in the (I think unlikely) event of
                  reading a 16-bit character 0xFFFF from a file with 16-bit encoding.

                  (How would such a character size read standard 8-bit files? By
                  zero-extending to 16?)

                  --
                  Bartc



                  Comment

                  • Keith Thompson

                    #10
                    Re: getc and &quot;large&quo t; bytes

                    vippstar@gmail. com writes:
                    On May 23, 6:42 pm, Richard Heathfield <r...@see.sig.i nvalidwrote:
                    >vipps...@gmail .com said:
                    >>
                    On May 23, 6:35 pm, Ben Pfaff <b...@cs.stanfo rd.eduwrote:
                    >vipps...@gmail .com writes:
                    Assuming all the values of int are in the range of unsigned char, what
                    happends if getc returns EOF?
                    >>
                    >Your assumption is false.
                    Would you please elaborate?
                    >>
                    >The int type must be able to represent values in the range INT_MIN to -1,
                    >none of which values are in the range of unsigned char (which, lacking a
                    >sign bit, cannot represent negative values).
                    I'm talking about the case that both int and unsigned char are 16
                    bits, and to be honest I'm still not convinced that this is false.
                    Your underlying point is right; you just stated it incorrectly. The
                    problem occurs when not all values of unsigned char are in the range
                    of int.

                    The value returned by getc() is either the next character from the
                    input stream, interpreted as an unsigned char and converted to int, or
                    the value EOF (which must be negative and is typically -1).

                    On most systems, all values of type unsigned char can be converted to
                    int without changing their numeric value.

                    If both int and unsigned char are 16 bits, then (a) the conversion
                    from unsigned char to int is implementation-defined for values
                    numerically greater than INT_MAX, and (b) some valid unsigned char
                    value might be converted to the value EOF.

                    You can work around (b) by checking feof() and ferror() after getc()
                    returns EOF. If both are false, then you can assume that you read a
                    legimate character (say, 0xFFFF) that happened to be converted to EOF
                    (or that there's a bug in the implementation' s feof() or ferror()
                    function, which might be almost as likely). Most programmers don't
                    bother to worry about this possibility. As a result, some code will
                    likely break if ported to such a system (most likely a DSP, which
                    probably has a freestanding implementation anyway and thus needn't
                    support <stdio.hat all) *if* it happens to read such a character.

                    (a) the implementation-definedness of the conversion, could be a more
                    serious problem. Given this problem, I can't think of a way to write
                    *really* portable code to read from a file.

                    fread() is likely to copy the input directly into an array of
                    characters, and thus probably won't run into the same problem -- but
                    fread() is defined to work by calling fgetc(), so the standard doesn't
                    guarantee that you won't run into exactly the same problem.

                    In my opinion, it would be reasonable for the standard to require
                    INT_MAX >= UCHAR_MAX for all hosted implementations .

                    --
                    Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                    Nokia
                    "We must do something. This is something. Therefore, we must do this."
                    -- Antony Jay and Jonathan Lynn, "Yes Minister"

                    Comment

                    • Richard Heathfield

                      #11
                      Re: getc and &quot;large&quo t; bytes

                      Bartc said:
                      >
                      "Ben Pfaff" <blp@cs.stanfor d.eduwrote in message
                      <snip>
                      >-1 is in the range of int.
                      >-1 is not in the range of unsigned char.
                      >Therefore it is not true that all the values of int are in the
                      >range of unsigned char.
                      >
                      The OP mentioned an example where both might be 16 bits.
                      That doesn't affect Ben's counter-example (or my range of counter-examples,
                      presented earlier).
                      So -1 in one
                      could be 0xFFFF in the other, causing ambiguity
                      There is no ambiguity here. 0xFFFF is an integer constant with the value
                      65535. This is not equal to -1.

                      --
                      Richard Heathfield <http://www.cpax.org.uk >
                      Email: -http://www. +rjh@
                      Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
                      "Usenet is a strange place" - dmr 29 July 1999

                      Comment

                      • Keith Thompson

                        #12
                        Re: getc and &quot;large&quo t; bytes

                        "Bartc" <bc@freeuk.comw rites:
                        "Ben Pfaff" <blp@cs.stanfor d.eduwrote in message
                        news:87y7617zqb .fsf@blp.benpfa ff.org...
                        >vippstar@gmail. com writes:
                        >>
                        >>On May 23, 6:35 pm, Ben Pfaff <b...@cs.stanfo rd.eduwrote:
                        >>>vipps...@gma il.com writes:
                        >>Assuming all the values of int are in the range of unsigned char, what
                        >>happends if getc returns EOF?
                        >>>>
                        >>>Your assumption is false.
                        >>Would you please elaborate?
                        >>
                        >-1 is in the range of int.
                        >-1 is not in the range of unsigned char.
                        >Therefore it is not true that all the values of int are in the
                        >range of unsigned char.
                        >
                        The OP mentioned an example where both might be 16 bits. So -1 in one could
                        be 0xFFFF in the other, causing ambiguity in the (I think unlikely) event of
                        reading a 16-bit character 0xFFFF from a file with 16-bit encoding.
                        No, -1 and 0xFFFF are two different values. It's possible that one of
                        those values is the result of converting the other.
                        (How would such a character size read standard 8-bit files? By
                        zero-extending to 16?)
                        It would be implementation-defined, or perhaps undefined.

                        For such an implementation to see an 8-bit file, the file would have
                        to have been copied to the system, or at least made visible somehow.
                        Such copying might necessarily involve some sort of conversion. The
                        conversion is outside the scope of C.

                        --
                        Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                        Nokia
                        "We must do something. This is something. Therefore, we must do this."
                        -- Antony Jay and Jonathan Lynn, "Yes Minister"

                        Comment

                        • Keith Thompson

                          #13
                          Re: getc and &quot;large&quo t; bytes

                          Eric Sosman <Eric.Sosman@su n.comwrites:
                          [...]
                          It seems to me that the behavior required of getc() places
                          far-reaching requirements on implementations where `int' and
                          `char' have the same width. Here are a few:
                          >
                          1) Since `unsigned char' can represent 2**N distinct values
                          and all of these must be distinguishable when converted to `int',
                          it follows that `int' must also have 2**N distinct values. Thus,
                          signed-magnitude and ones' complement representations are ruled
                          out, and INT_MIN must have its most negative possible value
                          (that is, INT_MIN == -INT_MAX - 1, all-bits-set cannot be a trap
                          representation) .
                          [...]

                          How do you conclude that all 2**N distinct values of type unsigned
                          char must be distinguishable when converted to int? The result of the
                          conversion is implementation-defined. If, for example, int has the
                          range -32768 .. +32767, and unsigned char has the range 0 .. 65536, I
                          see nothing in the standard that forbids converting all unsigned char
                          values greater than 32767 to 32767 (saturation). It would break
                          stdio, but I'm not convinced that that would make it non-conforming
                          (particularly for a freestanding implementation that needn't provide
                          stdio).

                          --
                          Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                          Nokia
                          "We must do something. This is something. Therefore, we must do this."
                          -- Antony Jay and Jonathan Lynn, "Yes Minister"

                          Comment

                          • Richard Tobin

                            #14
                            Re: getc and &quot;large&quo t; bytes

                            In article <ln4p8p2bkx.fsf @nuthaus.mib.or g>,
                            Keith Thompson <kst-u@mib.orgwrote:
                            >In my opinion, it would be reasonable for the standard to require
                            >INT_MAX >= UCHAR_MAX for all hosted implementations .
                            An implementation with, say, 16-bit ints and chars is still likely to
                            have 8-bit data on disk and most other input sources. In which case
                            fgetc() could read 8-bit values, and have no problem. At least, I
                            don't konw of anything in the standard that prevents this.

                            One can imagine a future implementation that uses UTF-32-encoded
                            Unicode characters, and has 32-bit chars. In that case there is no
                            problem with text (because Unicode in fact only goes up to about
                            2^20), but binary data would still have the problem.

                            -- Richard
                            --
                            In the selection of the two characters immediately succeeding the numeral 9,
                            consideration shall be given to their replacement by the graphics 10 and 11 to
                            facilitate the adoption of the code in the sterling monetary area. (X3.4-1963)

                            Comment

                            • Richard Tobin

                              #15
                              Re: getc and &quot;large&quo t; bytes

                              In article <NHCZj.8329$DZ6 .3770@text.news .virginmedia.co m>,
                              Bartc <bc@freeuk.comw rote:
                              >The OP mentioned an example where both might be 16 bits. So -1 in one could
                              >be 0xFFFF in the other, causing ambiguity in the (I think unlikely) event of
                              >reading a 16-bit character 0xFFFF from a file with 16-bit encoding.
                              There is a problem with chars and ints of equal size, but the OP
                              expressed it wrongly: he talked about "all the values of int [being]
                              in the range of unsigned char" - which can't happen, because negative
                              ints aren't in the range of unsigned char. The right way to put it is
                              that some of the values of unsigned char are not representable as int.

                              -- Richard
                              --
                              In the selection of the two characters immediately succeeding the numeral 9,
                              consideration shall be given to their replacement by the graphics 10 and 11 to
                              facilitate the adoption of the code in the sterling monetary area. (X3.4-1963)

                              Comment

                              Working...