signed vs unsigned

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • LuB

    signed vs unsigned

    This isn't a C++ question per se ... but rather, I'm posting this bcs I
    want the answer from a C++ language perspective. Hope that makes sense.

    I was reading Peter van der Linden's "Expert C Programming: Deep C
    Secrets" and came across the following statement:

    "Avoid unnecessary complexity by minimizing your use of unsigned types.
    Specifically, don't use an unsigned type to represent a quantity just
    because it will never be negative (e.g., "age" or "national_debt" )."

    Admittedly, I minimize comments in my code. I use them when necessary
    but try to limit them to one or two lines. I just don't like their
    aesthetic affect in the source. I find the code much harder to read
    littered with paragraphs of explanations.

    I find the code easier to read when broken up with appropriate newlines
    and small, short comments acting as headings.

    So - that effectually means that I try my darndest to write
    self-describing code. Shorter functions, self-explanatory names for
    functions and variable names, etc. Sometimes exceessive commenting is
    necessary, but as a whole, I tend to avoid it.

    I'm really enjoying Peter's book, but I find this comment hard to
    swallow considering that if an age or array index can never be negative
    - I would want to illustrate that with an apporpriate choice of type -
    namely, unsigned int.

    Am I in the minority here? Is my predilection considered poor style?

    I guess, from the compiler's standpoint ... using int everywhere is
    more portable ... since comparison's against unsigned int can vary
    between K&R and ANSI C.

    I'm not incurring some type of performance penalty for such decisions
    am I?

    Thanks in advance,

    -Luther

  • Bob Hairgrove

    #2
    Re: signed vs unsigned

    On 21 Feb 2006 08:58:23 -0800, "LuB" <lutherbaker@ya hoo.com> wrote:
    [color=blue]
    >I'm really enjoying Peter's book, but I find this comment hard to
    >swallow considering that if an age or array index can never be negative
    >- I would want to illustrate that with an apporpriate choice of type -
    >namely, unsigned int.
    >
    >Am I in the minority here?[/color]

    Hopefully not!
    [color=blue]
    >Is my predilection considered poor style?[/color]

    Absolutely not!

    The key to dealing with signed vs. unsigned is not to mix them, if
    possible, in comparisons. Be especially wary of comparing an unsigned
    counter value to 0 while decrementing the counter.

    --
    Bob Hairgrove
    NoSpamPlease@Ho me.com

    Comment

    • Cory Nelson

      #3
      Re: signed vs unsigned

      Like you said, marking a type as "unsigned" if for nothing else is an
      easy documentation for other developers that it will never be negative.
      I havn't read his stuff but I can't imagine what complexities he is
      talking about.

      Performance differences depend largly on your architecture. On AMD64,
      division/modulus are faster when using unsigned types. Conversion to
      floating point is faster with signed types. Addition/subtraction are
      the same.

      Comment

      • roberts.noah@gmail.com

        #4
        Re: signed vs unsigned


        LuB wrote:[color=blue]
        > I'm really enjoying Peter's book, but I find this comment hard to
        > swallow considering that if an age or array index can never be negative
        > - I would want to illustrate that with an apporpriate choice of type -
        > namely, unsigned int.[/color]

        The only reason that I can think of that you might want to not use
        'unsigned' is if the assumption that it will never be negative might
        change. However, most times you are better off with the assumption and
        the protection of the unsigned type and then change it later if you
        have to. Minimize dependencies on the type so that it is easier to do.

        The great thing about unsigned is if the value can't be negative and
        you use signed then you always have to check it. Simply defining the
        type as unsigned gets rid of all that as well as documenting your
        domain.

        Comment

        • Tomás

          #5
          Re: signed vs unsigned

          LuB posted:
          [color=blue]
          > This isn't a C++ question per se ... but rather, I'm posting this bcs I
          > want the answer from a C++ language perspective. Hope that makes sense.
          >
          > I was reading Peter van der Linden's "Expert C Programming: Deep C
          > Secrets" and came across the following statement:
          >
          > "Avoid unnecessary complexity by minimizing your use of unsigned types.
          > Specifically, don't use an unsigned type to represent a quantity just
          > because it will never be negative (e.g., "age" or "national_debt" )."
          >
          > Admittedly, I minimize comments in my code. I use them when necessary
          > but try to limit them to one or two lines. I just don't like their
          > aesthetic affect in the source. I find the code much harder to read
          > littered with paragraphs of explanations.
          >
          > I find the code easier to read when broken up with appropriate newlines
          > and small, short comments acting as headings.
          >
          > So - that effectually means that I try my darndest to write
          > self-describing code. Shorter functions, self-explanatory names for
          > functions and variable names, etc. Sometimes exceessive commenting is
          > necessary, but as a whole, I tend to avoid it.
          >
          > I'm really enjoying Peter's book, but I find this comment hard to
          > swallow considering that if an age or array index can never be negative
          > - I would want to illustrate that with an apporpriate choice of type -
          > namely, unsigned int.
          >
          > Am I in the minority here? Is my predilection considered poor style?
          >
          > I guess, from the compiler's standpoint ... using int everywhere is
          > more portable ... since comparison's against unsigned int can vary
          > between K&R and ANSI C.
          >
          > I'm not incurring some type of performance penalty for such decisions
          > am I?
          >
          > Thanks in advance,
          >
          > -Luther
          >[/color]


          My first rule is to write "const" wherever I can.
          (except for return types).

          My second rule is to write "unsigned" wherever I can.


          Thus I'll write:

          unsigned GetDogAge(unsig ned const age)
          {
          return age * 7;
          }

          Or alternatively re-use the parameter variable:

          unsigned GetDogAge(unsig ned age)
          {
          return age *= 7;
          }


          -Tomás

          Comment

          • Daniel T.

            #6
            Re: signed vs unsigned

            In article <1140542925.375 975.294960@f14g 2000cwb.googleg roups.com>,
            roberts.noah@gm ail.com wrote:
            [color=blue]
            > The great thing about unsigned is if the value can't be negative and
            > you use signed then you always have to check it. Simply defining the
            > type as unsigned gets rid of all that as well as documenting your
            > domain.[/color]

            And the bad thing about unsigned is that if code would otherwise make
            the value negative, you can't check it. IE

            void foo( unsigned s ) {
            // at this point s == 4294966272
            // is it an error (s came in as -1024) or
            // does the client really want us to deal with that number?
            }

            Bjarne Stroustrup says, "The unsigned integer types are ideal for uses
            that treat storage as a bit array. Using an unsigned instead of an int
            to gain one more bit to represent positive integers is almost never a
            good idea. Attempts to ensure that some values are positive by declaring
            variables unsigned will typically be defeated by the implicit conversion
            rules."

            --
            Magic depends on tradition and belief. It does not welcome observation,
            nor does it profit by experiment. On the other hand, science is based
            on experience; it is open to correction by observation and experiment.

            Comment

            • roberts.noah@gmail.com

              #7
              Re: signed vs unsigned


              Tomás wrote:
              [color=blue]
              > Or alternatively re-use the parameter variable:
              >
              > unsigned GetDogAge(unsig ned age)
              > {
              > return age *= 7;
              > }[/color]

              Performs an unnecissary and unused assignment as age is automatic and
              will be gone after return.

              Comment

              • forkazoo

                #8
                Re: signed vs unsigned


                LuB wrote:[color=blue]
                > This isn't a C++ question per se ... but rather, I'm posting this bcs I
                > want the answer from a C++ language perspective. Hope that makes sense.
                >
                > I was reading Peter van der Linden's "Expert C Programming: Deep C
                > Secrets" and came across the following statement:
                >
                > "Avoid unnecessary complexity by minimizing your use of unsigned types.
                > Specifically, don't use an unsigned type to represent a quantity just
                > because it will never be negative (e.g., "age" or "national_debt" )."
                >[/color]
                <snip>[color=blue]
                > -Luther[/color]

                Well, it is a style issue, so many people will probably disagree with
                me. They are probably all right, and I would still be able to respect
                them :)

                That said, I personally use signed types almost all the time, even if
                something should never be negative. Every once in a while, I make a
                horribly stupid error in something like a file loading function.
                Suppose an object can have zero or more child objects. If my loader
                returns an object that claims to have -1024 children, then I know I've
                done something wrong, and it can be easier to track down bugs that
                compile and don't crash. If it just claims that there are a large
                positive number of children, it's not as easy to catch the error
                condition. There is even the wildly unlikely possibility that there is
                an error due to a hardware fault like bad RAM. (Though, the problems
                are almost always caused by me! Many people who are better programmers
                than me may find that hardware accounts for a greater percentage of
                problems than I do :)

                Also, I use negative values as intentional error codes and special
                cases. Some people consider this horrible style. I can respect that.
                But, for a lot of the things I do, it is the quickest, easiest,
                simplest, and clearest way to have a recoverable error. So, my
                hypothetical object loading function might return an object which
                claims -1 children if it failed to open the file, -2 if it failed to
                parse the file, -3 if the file contained invalid information, etc. I
                know, exceptions are probably better for most of these things, but my
                personal style is to write C++ that looks a lot like C, and uses
                occasional C++ features. It's just more inline with the way I think
                about the problems.

                Also, by always using signed types, I can avoid comparisons between
                signed and unsigned. It is also generally easier to catch overflow.
                After all, the national debt might never be negative, but it certainly
                might exceed MAX_INT on some systems! :)

                I tend to work alone on personal projects. So, the most important
                thing for me is that my personal coding style is readable - to me.
                Feel free to strongly disagree with my style.

                Comment

                • Neil Cerutti

                  #9
                  Re: signed vs unsigned

                  On 2006-02-21, Tomás <NULL@NULL.NULL > wrote:[color=blue]
                  > My first rule is to write "const" wherever I can.
                  > (except for return types).
                  >
                  > My second rule is to write "unsigned" wherever I can.[/color]

                  I don't agree with that rule.
                  [color=blue]
                  > Thus I'll write:
                  >
                  > unsigned GetDogAge(unsig ned const age)
                  > {
                  > return age * 7;
                  > }[/color]

                  What do you expect to happen if a client passes in an negative int?

                  The argument is not in the domain, yet the error has been rendered
                  impossible to detect or recover from.

                  --
                  Neil Cerutti

                  Comment

                  • Alf P. Steinbach

                    #10
                    Re: signed vs unsigned

                    * Neil Cerutti:[color=blue]
                    > On 2006-02-21, Tomás <NULL@NULL.NULL > wrote:[color=green]
                    >> My first rule is to write "const" wherever I can.
                    >> (except for return types).
                    >>
                    >> My second rule is to write "unsigned" wherever I can.[/color]
                    >
                    > I don't agree with that rule.
                    >[color=green]
                    >> Thus I'll write:
                    >>
                    >> unsigned GetDogAge(unsig ned const age)
                    >> {
                    >> return age * 7;
                    >> }[/color]
                    >
                    > What do you expect to happen if a client passes in an negative int?
                    >
                    > The argument is not in the domain, yet the error has been rendered
                    > impossible to detect or recover from.[/color]

                    I don't disagree with your viewpoint regarding using or not using
                    unsigned whenever possible; I think both are valid viewpoints, and as
                    with indentation the main thing is to be consistent in one's choices.

                    However, I disagree with your reason!

                    With the unsigned argument a validity test might go like

                    assert( age < 200 ); // unsigned validity test.

                    With a signed argument the test might go like

                    assert( age >= 0 ); // signed validity test.
                    assert( age < 200 ); // more signed validity test.

                    Now, first of all that demonstrates the "impossible to detect" is simply
                    incorrect, and second, in my view it demonstrates a slight superiority
                    for unsigned in this particular case, with respect to validity testing.

                    Cheers,

                    - Alf

                    --
                    A: Because it messes up the order in which people normally read text.
                    Q: Why is it such a bad thing?
                    A: Top-posting.
                    Q: What is the most annoying thing on usenet and in e-mail?

                    Comment

                    • roberts.noah@gmail.com

                      #11
                      Re: signed vs unsigned


                      Alf P. Steinbach wrote:[color=blue]
                      > * Neil Cerutti:[color=green]
                      > > On 2006-02-21, Tomás <NULL@NULL.NULL > wrote:[color=darkred]
                      > >> My first rule is to write "const" wherever I can.
                      > >> (except for return types).
                      > >>
                      > >> My second rule is to write "unsigned" wherever I can.[/color]
                      > >
                      > > I don't agree with that rule.
                      > >[color=darkred]
                      > >> Thus I'll write:
                      > >>
                      > >> unsigned GetDogAge(unsig ned const age)
                      > >> {
                      > >> return age * 7;
                      > >> }[/color]
                      > >
                      > > What do you expect to happen if a client passes in an negative int?
                      > >
                      > > The argument is not in the domain, yet the error has been rendered
                      > > impossible to detect or recover from.[/color]
                      >
                      > I don't disagree with your viewpoint regarding using or not using
                      > unsigned whenever possible; I think both are valid viewpoints, and as
                      > with indentation the main thing is to be consistent in one's choices.
                      >
                      > However, I disagree with your reason!
                      >
                      > With the unsigned argument a validity test might go like
                      >
                      > assert( age < 200 ); // unsigned validity test.
                      >
                      > With a signed argument the test might go like
                      >
                      > assert( age >= 0 ); // signed validity test.
                      > assert( age < 200 ); // more signed validity test.
                      >
                      > Now, first of all that demonstrates the "impossible to detect" is simply
                      > incorrect, and second, in my view it demonstrates a slight superiority
                      > for unsigned in this particular case, with respect to validity testing.[/color]

                      I believe he is talking about something like this:


                      #include <iostream>
                      using namespace std;

                      unsigned int GetDogAge(unsig ned int age)
                      {
                      return age * 7;
                      }

                      int main(int argc, char* argv[])
                      {
                      int t = -5;
                      unsigned int x = GetDogAge(t);

                      cout << x;

                      int y; cin >> y;

                      return 0;
                      }

                      ------ Build started: Project: Playground, Configuration: Debug Win32
                      ------

                      Compiling...
                      Playground.cpp
                      Linking...

                      Build log was saved at
                      "file://c:\src\Playgrou nd\Playground\D ebug\BuildLog.h tm"
                      Playground - 0 error(s), 0 warning(s)


                      ---------------------- Done ----------------------

                      Build: 1 succeeded, 0 failed, 0 skipped

                      Output is, "4294967261 ."



                      It is an interesting point.

                      Comment

                      • andy@servocomm.freeserve.co.uk

                        #12
                        Re: signed vs unsigned

                        Daniel T. wrote:[color=blue]
                        > In article <1140542925.375 975.294960@f14g 2000cwb.googleg roups.com>,
                        > roberts.noah@gm ail.com wrote:
                        >[color=green]
                        > > The great thing about unsigned is if the value can't be negative and
                        > > you use signed then you always have to check it. Simply defining the
                        > > type as unsigned gets rid of all that as well as documenting your
                        > > domain.[/color]
                        >
                        > And the bad thing about unsigned is that if code would otherwise make
                        > the value negative, you can't check it. IE
                        >
                        > void foo( unsigned s ) {
                        > // at this point s == 4294966272
                        > // is it an error (s came in as -1024) or
                        > // does the client really want us to deal with that number?
                        > }
                        >
                        > Bjarne Stroustrup says, "The unsigned integer types are ideal for uses
                        > that treat storage as a bit array. Using an unsigned instead of an int
                        > to gain one more bit to represent positive integers is almost never a
                        > good idea. Attempts to ensure that some values are positive by declaring
                        > variables unsigned will typically be defeated by the implicit conversion
                        > rules."[/color]

                        Sounds like a good excuse to write an unsigned_int class:

                        #include <boost/utility/enable_if.hpp>
                        #include <boost/numeric/conversion/converter.hpp>
                        #include <boost/type_traits/is_unsigned.hpp >

                        class unsigned_int{
                        unsigned int m_value;
                        public:
                        template <typename T>
                        unsigned_int(T const & rhs,
                        typename boost::enable_i f<
                        boost::is_unsig ned<T>,
                        void*[color=blue]
                        >::type = 0[/color]
                        )
                        {
                        // further features
                        // throws on overflow when T is bigger eg unsigned long
                        boost::numeric: :converter<unsi gned int,T> convert;
                        m_value = convert(rhs);
                        }
                        };

                        int main()
                        {
                        unsigned_int n1 = 1U;
                        unsigned_int n2 = static_cast<uns igned short>(1);
                        unsigned_int n3 = 1UL;
                        unsigned_int n4 = static_cast<uns igned int>(1);

                        unsigned_int n5 = 1; // Error!
                        }

                        reagrds
                        Andy Little

                        Comment

                        • andy@servocomm.freeserve.co.uk

                          #13
                          Re: signed vs unsigned


                          Daniel T. wrote:[color=blue]
                          > In article <1140542925.375 975.294960@f14g 2000cwb.googleg roups.com>,
                          > roberts.noah@gm ail.com wrote:
                          >[color=green]
                          > > The great thing about unsigned is if the value can't be negative and
                          > > you use signed then you always have to check it. Simply defining the
                          > > type as unsigned gets rid of all that as well as documenting your
                          > > domain.[/color]
                          >
                          > And the bad thing about unsigned is that if code would otherwise make
                          > the value negative, you can't check it. IE
                          >
                          > void foo( unsigned s ) {
                          > // at this point s == 4294966272
                          > // is it an error (s came in as -1024) or
                          > // does the client really want us to deal with that number?
                          > }
                          >
                          > Bjarne Stroustrup says, "The unsigned integer types are ideal for uses
                          > that treat storage as a bit array. Using an unsigned instead of an int
                          > to gain one more bit to represent positive integers is almost never a
                          > good idea. Attempts to ensure that some values are positive by declaring
                          > variables unsigned will typically be defeated by the implicit conversion
                          > rules."[/color]

                          Sounds like a good excuse for an unsigned_int class ...

                          #include <boost/utility/enable_if.hpp>
                          #include <boost/numeric/conversion/converter.hpp>
                          #include <boost/type_traits/is_unsigned.hpp >

                          class unsigned_int{
                          unsigned int m_value;
                          public:
                          template <typename T>
                          unsigned_int(T const & rhs,
                          typename boost::enable_i f<
                          boost::is_unsig ned<T>,
                          void*[color=blue]
                          >::type = 0[/color]
                          )
                          {
                          // further features
                          // throws on overflow when T is bigger eg unsigned long
                          boost::numeric: :converter<unsi gned int,T> convert;
                          m_value = convert(rhs);
                          }
                          };

                          int main()
                          {
                          unsigned_int n1 = 1U;
                          unsigned_int n2 = static_cast<uns igned short>(1);
                          unsigned_int n3 = 1UL;
                          unsigned_int n4 = static_cast<uns igned int>(1);

                          unsigned_int n5 = 1; // Error!
                          }

                          reagrds
                          Andy Little

                          Comment

                          • andy@servocomm.freeserve.co.uk

                            #14
                            Re: signed vs unsigned

                            Daniel T. wrote:[color=blue]
                            > In article <1140542925.375 975.294960@f14g 2000cwb.googleg roups.com>,
                            > roberts.noah@gm ail.com wrote:
                            >[color=green]
                            > > The great thing about unsigned is if the value can't be negative and
                            > > you use signed then you always have to check it. Simply defining the
                            > > type as unsigned gets rid of all that as well as documenting your
                            > > domain.[/color]
                            >
                            > And the bad thing about unsigned is that if code would otherwise make
                            > the value negative, you can't check it. IE
                            >
                            > void foo( unsigned s ) {
                            > // at this point s == 4294966272
                            > // is it an error (s came in as -1024) or
                            > // does the client really want us to deal with that number?
                            > }
                            >
                            > Bjarne Stroustrup says, "The unsigned integer types are ideal for uses
                            > that treat storage as a bit array. Using an unsigned instead of an int
                            > to gain one more bit to represent positive integers is almost never a
                            > good idea. Attempts to ensure that some values are positive by declaring
                            > variables unsigned will typically be defeated by the implicit conversion
                            > rules."[/color]

                            Sounds like a good excuse to write an unsigned_int class:

                            #include <boost/utility/enable_if.hpp>
                            #include <boost/numeric/conversion/converter.hpp>
                            #include <boost/type_traits/is_unsigned.hpp >

                            class unsigned_int{
                            unsigned int m_value;
                            public:
                            template <typename T>
                            unsigned_int(T const & rhs,
                            typename boost::enable_i f<
                            boost::is_unsig ned<T>,
                            void*[color=blue]
                            >::type = 0[/color]
                            )
                            {
                            // further features
                            // throws on overflow when T is bigger eg unsigned long
                            boost::numeric: :converter<unsi gned int,T> convert;
                            m_value = convert(rhs);
                            }
                            };

                            int main()
                            {
                            unsigned_int n1 = 1U;
                            unsigned_int n2 = static_cast<uns igned short>(1);
                            unsigned_int n3 = 1UL;
                            unsigned_int n4 = static_cast<uns igned int>(1);

                            unsigned_int n5 = 1; // Error!
                            }

                            reagrds
                            Andy Little

                            Comment

                            • andy@servocomm.freeserve.co.uk

                              #15
                              Re: signed vs unsigned


                              a...@servocomm. freeserve.co.uk wrote:

                              Sorry
                              Sorry
                              Sorry for posting 3 times. Browser hung up

                              regards
                              Andy Little

                              Comment

                              Working...