signed and unsigned char

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Christopher Benson-Manica

    #1

    signed and unsigned char

    Given

    signed char str_a[]="Hello, world!\n";
    unsigned char str_b[]="Hello, world!\n";

    what is the difference, if any, between the following two statements?

    printf( "%s", str_a );
    printf( "%s", str_b );

    If there is a difference, what is the best way to compare *str_a with
    0xFF? (On my implementation, unadorned char is signed, and so I'm
    using

    if( *str_a == (signed char)0xFF ) ...

    to quiet compiler warnings.)

    --
    Christopher Benson-Manica | I *should* know what I'm talking about - if I
    ataru(at)cybers pace.org | don't, I need to know. Flames welcome.
  • pete

    #2
    Re: signed and unsigned char

    Christopher Benson-Manica wrote:[color=blue]
    >
    > Given
    >
    > signed char str_a[]="Hello, world!\n";
    > unsigned char str_b[]="Hello, world!\n";
    >
    > what is the difference, if any, between the following two statements?
    >
    > printf( "%s", str_a );
    > printf( "%s", str_b );
    >
    > If there is a difference, what is the best way to compare *str_a with
    > 0xFF?[/color]

    char type arguments are converted to int.
    That result is converted to unsigned char for stdio output.
    There shouldn't be a problem there, regardless of sign of char.
    [color=blue]
    > (On my implementation, unadorned char is signed, and so I'm
    > using
    >
    > if( *str_a == (signed char)0xFF ) ...[/color]

    if( *(unsigned char*)str_a == -1 )

    /* assuming 0xff is meant to be all bits set */

    --
    pete

    Comment

    • Leor Zolman

      #3
      Re: signed and unsigned char

      On Thu, 12 Feb 2004 17:52:55 +0000 (UTC), Christopher Benson-Manica
      <ataru@nospam.c yberspace.org> wrote:
      [color=blue]
      >Given
      >
      >signed char str_a[]="Hello, world!\n";
      >unsigned char str_b[]="Hello, world!\n";
      >
      >what is the difference, if any, between the following two statements?
      >
      >printf( "%s", str_a );
      >printf( "%s", str_b );[/color]

      Other than that they take different arguments? None that I can see.
      There are no conversions to worry about, and once the pointer values
      land in printf, there's no way for printf to be able tell the
      difference anyway (and no reason for it to care).
      [color=blue]
      >
      >If there is a difference, what is the best way to compare *str_a with
      >0xFF? (On my implementation, unadorned char is signed, and so I'm
      >using
      >
      >if( *str_a == (signed char)0xFF ) ...
      >
      >to quiet compiler warnings.)[/color]

      I'm not sure how the 2nd question is dependent upon the first... What
      you've done is clearly showing your intent, which is a Good Thing. One
      alternative is
      if (*str_a == -1) ...
      but I like yours better.




      Leor Zolman
      BD Software
      leor@bdsoft.com
      www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
      C++ users: Download BD Software's free STL Error Message
      Decryptor at www.bdsoft.com/tools/stlfilt.html

      Comment

      • Martin Johansen

        #4
        Re: signed and unsigned char


        "Christophe r Benson-Manica" <ataru@nospam.c yberspace.org> wrote in message
        news:c0gehn$ek0 $1@chessie.cirr .com...[color=blue]
        > Given
        >
        > signed char str_a[]="Hello, world!\n";
        > unsigned char str_b[]="Hello, world!\n";
        >
        > what is the difference, if any, between the following two statements?
        >
        > printf( "%s", str_a );
        > printf( "%s", str_b );[/color]

        '^' != (unsigned char)'^' for example.

        Extended ascii chars have negative values (since they are higher than 127).


        Comment

        • Christopher Benson-Manica

          #5
          Re: signed and unsigned char

          pete <pfiland@mindsp ring.com> spoke thus:
          [color=blue]
          > if( *(unsigned char*)str_a == -1 )[/color]

          1) Is that better than ... (unsigned char)*str_a ... ?
          2) This relies on -1's representation being all bits set, yes?

          --
          Christopher Benson-Manica | I *should* know what I'm talking about - if I
          ataru(at)cybers pace.org | don't, I need to know. Flames welcome.

          Comment

          • Eric Sosman

            #6
            Re: signed and unsigned char

            pete wrote:[color=blue]
            >
            > Christopher Benson-Manica wrote:[color=green]
            > >
            > > Given
            > >
            > > signed char str_a[]="Hello, world!\n";
            > > unsigned char str_b[]="Hello, world!\n";
            > >
            > > what is the difference, if any, between the following two statements?
            > >
            > > printf( "%s", str_a );
            > > printf( "%s", str_b );
            > >
            > > If there is a difference, what is the best way to compare *str_a with
            > > 0xFF?[/color]
            >
            > char type arguments are converted to int.[/color]

            True (usually), but irrelevant: the arguments are not
            any kind of `char', but are pointers.
            [color=blue]
            > That result is converted to unsigned char for stdio output.[/color]

            Either the Standard doesn't say so, or I've overlooked
            the spot where it does.
            [color=blue]
            > There shouldn't be a problem there, regardless of sign of char.[/color]

            There isn't a problem, because the "%s" specifier is defined
            to work with any of `char*', `unsigned char*', and `signed char*'.
            Something of an oddity, really: Most conversion specifiers are
            very strict about the type of the corresponding argument, yet
            here's one that accepts arguments of three distinct types.
            [color=blue][color=green]
            > > (On my implementation, unadorned char is signed, and so I'm
            > > using
            > >
            > > if( *str_a == (signed char)0xFF ) ...[/color][/color]

            Undefined behavior, I think. You might do better with

            if ( (unsigned char)*str == 0xFF )

            --
            Eric.Sosman@sun .com

            Comment

            • pete

              #7
              Re: signed and unsigned char

              Christopher Benson-Manica wrote:[color=blue]
              >
              > pete <pfiland@mindsp ring.com> spoke thus:
              >[color=green]
              > > if( *(unsigned char*)str_a == -1 )[/color]
              >
              > 1) Is that better than ... (unsigned char)*str_a ... ?[/color]

              No. Now, I like
              if( (unsigned char)*str_a == (unsigned char)-1)
              or
              if( (unsigned char)*str_a == (unsigned char)0xFF)
              best.
              [color=blue]
              > 2) This relies on -1's representation being all bits set, yes?[/color]

              If str_a points to an all bits set byte,
              then *(unsigned char*)str_a will equal ((unsigned char)-1)

              then the question becomes, is
              ((unsigned char)-1) equal to (-1) ?
              and it isn't, so I was wrong.

              if( (unsigned char)*str_a == (unsigned char)0xFF )

              The conversion of out of range values to signed char,
              is implementation defined, so I would avoid it.
              The conversion of everything to unsigned char, is well defined.

              0xff is of type int.

              --
              pete

              Comment

              • Jeremy Yallop

                #8
                Re: signed and unsigned char

                Eric Sosman wrote:[color=blue]
                > pete wrote:[color=green]
                >> That result is converted to unsigned char for stdio output.[/color]
                >
                > Either the Standard doesn't say so, or I've overlooked
                > the spot where it does.[/color]

                I think pete's right. "Byte output" functions, printf included, are
                defined in terms of fputc:

                The byte output functions write characters to the stream as if by
                successive calls to the fputc function. [7.19.3#12]

                and the description of fputc says:

                The fputc function writes the character specified by c (converted
                to an unsigned char) to the output stream pointed to by stream
                [...] [7.19.7.3#2]

                Jeremy.

                Comment

                • Leor Zolman

                  #9
                  Re: signed and unsigned char

                  On Thu, 12 Feb 2004 18:16:12 GMT, Leor Zolman <leor@bdsoft.co m> wrote:
                  [color=blue][color=green]
                  >>
                  >>if( *str_a == (signed char)0xFF ) ...
                  >>[/color][/color]

                  oops, of course that's UB... Eric caught it.

                  Leor Zolman
                  BD Software
                  leor@bdsoft.com
                  www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
                  C++ users: Download BD Software's free STL Error Message
                  Decryptor at www.bdsoft.com/tools/stlfilt.html

                  Comment

                  • Keith Thompson

                    #10
                    Re: signed and unsigned char

                    "Martin Johansen" <martinfj@is.on line.no> writes:[color=blue]
                    > "Christophe r Benson-Manica" <ataru@nospam.c yberspace.org> wrote in message
                    > news:c0gehn$ek0 $1@chessie.cirr .com...[color=green]
                    > > Given
                    > >
                    > > signed char str_a[]="Hello, world!\n";
                    > > unsigned char str_b[]="Hello, world!\n";
                    > >
                    > > what is the difference, if any, between the following two statements?
                    > >
                    > > printf( "%s", str_a );
                    > > printf( "%s", str_b );[/color]
                    >
                    > '^' != (unsigned char)'^' for example.
                    >
                    > Extended ascii chars have negative values (since they are higher than 127).[/color]

                    <Slightly OT>
                    Actually the ASCII value of '^' is 94 (unless my newsreader mangled
                    whatever extended ASCII character you actually wrote).
                    </Slightly OT>

                    All the characters in the string literals above are in the "basic
                    execution character set". C99 6.2.5p3 says:

                    If a member of the basic execution character set is stored in a
                    char object, its value is guaranteed to be positive.

                    In ASCII, all such characters happen to have values in the range
                    32..126. In EBCDIC, if I recall correctly, some basic characters have
                    codes greater than 127; I think this implies that in an implementation
                    that uses EBCDIC as its execution character set, type char must be
                    unsigned (assuming CHAR_BIT==8).

                    --
                    Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                    San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
                    Schroedinger does Shakespeare: "To be *and* not to be"

                    Comment

                    • Richard Bos

                      #11
                      Re: signed and unsigned char

                      pete <pfiland@mindsp ring.com> wrote:
                      [color=blue]
                      > Christopher Benson-Manica wrote:[color=green]
                      > >
                      > > signed char str_a[]="Hello, world!\n";
                      > > unsigned char str_b[]="Hello, world!\n";
                      > >
                      > > what is the difference, if any, between the following two statements?
                      > >
                      > > printf( "%s", str_a );
                      > > printf( "%s", str_b );
                      > >
                      > > If there is a difference, what is the best way to compare *str_a with
                      > > 0xFF?[/color]
                      >
                      > char type arguments are converted to int.[/color]

                      They're not char type arguments, they're _pointers_ to char.

                      AFAICT pointers to signed and unsigned types must behave the same, btw.
                      [color=blue][color=green]
                      > > (On my implementation, unadorned char is signed, and so I'm
                      > > using
                      > >
                      > > if( *str_a == (signed char)0xFF ) ...[/color][/color]

                      Not perfectly guaranteed to work. Conversion of unsigned values to
                      signed types, when they're out of range, is implementation-defined. It's
                      not undefined, which means that at least it's guaranteed not to give
                      false negatives (0xFF must be converted to _some_ signed char value, not
                      to random junk), but it may give false positives (AFAICT, it's legal for
                      some other value to convert to the same signed char as 0xFF).

                      if ((unsigned char)*str_a == 0xFF)

                      should be perfectly defined, but will not do what you expect if chars
                      are more than eight bits. OTOH,

                      if ((unsigned char)*str_a == UCHAR_MAX)

                      is also well-defined, but will not compare to 0xFF when CHAR_BIT > 8.

                      Richard

                      Comment

                      • Richard Bos

                        #12
                        Re: signed and unsigned char

                        Eric Sosman <Eric.Sosman@su n.com> wrote:
                        [color=blue][color=green]
                        > > Christopher Benson-Manica wrote:[color=darkred]
                        > > > (On my implementation, unadorned char is signed, and so I'm
                        > > > using
                        > > >
                        > > > if( *str_a == (signed char)0xFF ) ...[/color][/color]
                        >
                        > Undefined behavior, I think.[/color]

                        Implementation-defined, surely?

                        Richard

                        Comment

                        • pete

                          #13
                          Re: signed and unsigned char

                          Richard Bos wrote:[color=blue]
                          >
                          > pete <pfiland@mindsp ring.com> wrote:
                          >[color=green]
                          > > Christopher Benson-Manica wrote:[color=darkred]
                          > > >
                          > > > signed char str_a[]="Hello, world!\n";
                          > > > unsigned char str_b[]="Hello, world!\n";
                          > > >
                          > > > what is the difference, if any, between the following two statements?
                          > > >
                          > > > printf( "%s", str_a );
                          > > > printf( "%s", str_b );
                          > > >
                          > > > If there is a difference, what is the best way to compare *str_a with
                          > > > 0xFF?[/color]
                          > >
                          > > char type arguments are converted to int.[/color]
                          >
                          > They're not char type arguments, they're _pointers_ to char.[/color]

                          I was considering printf, as a byte output function,
                          defined in terms of fputc as per Jeremy Yallop's
                          last post in this thread.



                          --
                          pete

                          Comment

                          • Christopher Benson-Manica

                            #14
                            Re: signed and unsigned char

                            pete <pfiland@mindsp ring.com> spoke thus:
                            [color=blue]
                            > If str_a points to an all bits set byte,
                            > then *(unsigned char*)str_a will equal ((unsigned char)-1)[/color]

                            Is that guaranteed? (non-rhetorical question)

                            --
                            Christopher Benson-Manica | I *should* know what I'm talking about - if I
                            ataru(at)cybers pace.org | don't, I need to know. Flames welcome.

                            Comment

                            • pete

                              #15
                              Re: signed and unsigned char

                              Christopher Benson-Manica wrote:[color=blue]
                              >
                              > pete <pfiland@mindsp ring.com> spoke thus:
                              >[color=green]
                              > > If str_a points to an all bits set byte,
                              > > then *(unsigned char*)str_a will equal ((unsigned char)-1)[/color]
                              >
                              > Is that guaranteed? (non-rhetorical question)[/color]

                              Yes.
                              For the type unsigned char, there are only value bits;
                              there are no padding bits and there is no sign bit.
                              The expression
                              *(unsigned char*)str_a
                              will cause the byte at str_a,
                              to be evaluated by it's bit pattern,
                              according to the rules for the representation of unsigned char.

                              (-1) cast to any unsigned type,
                              is the MAX value for that unsigned type,
                              which is, all value bits, set to one.

                              --
                              pete

                              Comment

                              Working...