Thread: Signed vs Unsigned int

  1. #1
    Registered User
    Join Date
    Aug 2006
    Posts
    3

    Signed vs Unsigned int

    I have a question as to what the better programming practice would be if I have a function that takes an integer input to determine the size of an array.

    1. Use an unsigned int. This seems like the logical answer at first except that if a user were to enter a negative number to be passed to the function this would result in the creation of a verry large array.

    2. Or, use a signed int and check for a negative value before creating the array.
    This also raises the question: If a negative input is recieved should I Throw an error and terminate the program, or simply change the value to a positive value...?

    3. Any other suggestions/ideas

  2. #2
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    #2. Unsigned ints are implicitly cast when they're assigned a signed value.
    Code:
    #include <iostream>
    
    int main() {
        unsigned int foo = -1;
        
        std::cout << foo;
        
        return 0;
    }
    
    /* Output:
       4294967295
    */
    That index would surely lead to a segmentation fault.

    You should try and declare your arrays with a constant as the index, that way you always have a max if you need to do bounds checks.
    Quote Originally Posted by osyrez
    This also raises the question: If a negative input is recieved should I Throw an error and terminate the program, or simply change the value to a positive value...?
    Always, always, always, throw an error... never, ever assume the user wanted to do something they didn't.
    Last edited by SlyMaelstrom; 08-16-2006 at 07:24 PM.
    Sent from my iPadŽ

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    I would have it take an unsigned int. A negative value doesn't make sense. Making it an unsigned int makes it clear that a negative value is invalid. If the user sends an negative number, it is their error.

  4. #4
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Quote Originally Posted by Daved
    I would have it take an unsigned int. A negative value doesn't make sense. Making it an unsigned int makes it clear that a negative value is invalid. If the user sends an negative number, it is their error.
    Agreed, but I take the question to say, "I'll make it an unsigned int, and then all I have to do is check to see that it isn't negative and then it's OK". Personally, if you're going to do bounds checks, anyway, it doesn't really matter. Whether it's signed or not, unless its between 0 and the size of the array, it will fail your bounds check.
    Sent from my iPadŽ

  5. #5
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    You have several options. But if you depend on user input to decide the size of an array you are better off with a signed int. Otherwise do go for a const unsigned int.

    The reason why you will want your dynamic array size to be a signed int is because you can give feedback to the user in case he enters a negative value. As SlyMaelstrom suggested, if you use a unsigned int, you lose this option.

    Now... you also need to do some range checking prior or during array creation. Here you have a little bit more to consider. Do you have or not a conceptual limit as to how big the array can be? If you do, you can validate the input when you are checking for negative values. If you don't know exactly how big the array can be, then the best option is to have the array creation within a try block and look for a segfault (catch std::length_error)

    This is probably a better approach because its conceivable that users have varied machine resources.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    I don't understand the point of using a signed int. You are not allowed to have a negative number, so why would you allow one? If you are worried about a negative number being converted into a positive number that is too big, then you also must be worried about regular positive numbers that are too big, so that shouldn't affect the signed/unsigned decision.

    Most (all?) standard libraries use unsigned numbers for this type of thing.

  7. #7
    Registered User
    Join Date
    Aug 2006
    Posts
    3
    Thank you all for your input, It seems clear that an const unsigned int would be the best choice while checking for a segfault error. I had assumed that creating an array of such a large size would cause some kind of an error on most systems but wasn't sure what to do about it.

  8. #8
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    I'm just looking at it from the user perspective. It has the potential to provide more feedback. Maybe the user didn't understand what is being asked of him, or cannot understand why such a small number as -1 returns an error saying it is too big (highly dependant on the error message returned by the coder, true).

    I'm not big on it. Just think that there is always an advantage in reacting to the exact input, instead of input that gets altered behind the scenes. Probably it makes little sense if the user is being asked how many Light Infantry he wants to create this turn, for instance.

    EDIT: as a side note,

    Most (all?) standard libraries use unsigned numbers for this type of thing.
    but the user of the STL is the coder who should know better. the user of the app is the end user, who may not know any better.
    Last edited by Mario F.; 08-16-2006 at 09:15 PM.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  9. #9
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by osyrez
    3. Any other suggestions/ideas
    If user input, read as a string. First attempt to convert to a signed value. If successful and the value is negative, complain. If not, and if you need to, attempt to convert to an unsigned value. If successful, be happy.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  10. #10
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Quote Originally Posted by osyrez
    I had assumed that creating an array of such a large size would cause some kind of an error on most systems but wasn't sure what to do about it.
    Creating an array of that size isn't only an error for most systems, it's an error for a compiler. You simply can't have an array of that size.
    Code:
    const unsigned int USIGN_MAX = (unsigned int)-1; // The largest unsigned value
    const signed int SIGN_MAX = USIGN_MAX / 2; // The largest signed value
    
    int main() {
       int foo[SIGN_MAX] = { 0 };
       return 0;
    }
    On my computer, SIGN_MAX was 2147483647. Which would make this a 32 bit integer. Now, if you do the math (We'll make it 2147483648 to remain in integers).
    Code:
    2147483648 
       times 4 bytes
       equals 8589934592 bytes
       divided by 1024
       equals 8388608 kilobytes
       divided by 1024 
       equals 8182 megabytes
       divided by 1024
       equals 8 gigabytes of memory
    You can see why this is a problem. Your compile may let you get away with this with a char, but if you plan on initializing it, good luck getting it to run.
    Last edited by SlyMaelstrom; 08-16-2006 at 09:28 PM.
    Sent from my iPadŽ

  11. #11
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Another approach I saw recently was to use some RSIZE_MAX and test against it.
    Quote Originally Posted by n1135
    2 The macro is

    RSIZE_MAX

    which expands to a value6) of type size_t. Functions that have parameters of type rsize_t consider it a runtime-constraint violation if the values of those parameters are greater than RSIZE_MAX.

    Recommended practice

    3 Extremely large object sizes are frequently a sign that an object’s size was calculated incorrectly. For example, negative numbers appear as very large positive numbers when converted to an unsigned type like size_t. Also, some implementations do not support objects as large as the maximum value that can be represented by type size_t.

    4 For those reasons, it is sometimes beneficial to restrict the range of object sizes to detect programming errors. For implementations targeting machines with large address spaces, it is recommended that RSIZE_MAX be defined as the smaller of the size of the largest object supported or (SIZE_MAX >> 1), even if this limit is smaller than the size of some legitimate, but very large, objects. Implementations targeting machines with small address spaces may wish to define RSIZE_MAX as SIZE_MAX, which means that there is no object size that is considered a runtime-constraint violation.
    (page 17 of 89 page pdf)
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  12. #12
    Registered User
    Join Date
    Aug 2006
    Posts
    3
    Quote Originally Posted by SlyMaelstrom
    Code:
    2147483648 
       times 4 bytes
       equals 8589934592 bytes
       divided by 1024
       equals 8388608 kilobytes
       divided by 1024 
       equals 8182 megabytes
       divided by 1024
       equals 8 gigabytes of memory
    You can see why this is a problem. Your compile may let you get away with this with a char, but if you plan on initializing it, good luck getting it to run.
    ick.... ya I see what you mean.

    So I'm assuming the max size an array can have is determined by how much avaliable memory a system has. If this is the case then one could find out how much memory is avaliable before creation of the dynamic array and determine from that what the maximum size of the array could be. Of course that would leave no room for anything else so that wouldn't be desirable. Now I suppose one could subtract off of that an amount that would leave a reasonable amount of memory for the system to run normaly. But then again that is quite a large chunk of memory to be allocating for one array, and that would also limit the use of the function. Although I'm hesitant to set a limit to a possible array size, it seems like the best option so far. I would just need to figure out what the largest array size I could need for my purpose and maybee add a bit just to be sure.

    On that note I'm thinking of doing somthing of the sort

    Code:
    #define MAX_ARRAY_SIZE  1000
    
    
    function(const unsigned);
    
    int main()
    {
    
    ... return 0;
    } void function(const unsigned size) {
    if (size > MAX_ARRAY_SIZE) {
    throw some_error;
    }
    }
    using #define to set my maximum size for all arrays in the program and allowing my to easily change that value if needed.

  13. #13
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    No, no, no, and no... just stop what you're thinking and back up. Forget about checking system resources, system memory, or anything like that... If you're creating an array that could potentially cause system instability it's so large then you are already doing something wrong. Arrays suck... period. They're good for very small things in C++. If you're handling a lot of data, look to containers like vectors and queues. They'll automatically allocate, deallocate, resize everything for you. No need to decide at the beginning how much memory you need or can afford. If your container gets too large, then you can store it in a file on the harddrive (god forbid) and use it like a swap file.
    Sent from my iPadŽ

  14. #14
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> the user of the STL is the coder who should know better. the user of the app is the end user, who may not know any better.
    I'm assuming we're talking about the user of the function, not the user of the app. If the input is coming from an actual program user, it should be checked before being sent to the function.

    >> If you're handling a lot of data, look to containers like vectors and queues.
    While I agree, vectors or deques are preferred to plain dynamic arrays, I don't think it would matter much in this instance. Either way there will be some number that will cause the program to run out of memory. The OP must be referring to dynamic arrays, since static arrays must be sized with a compile time constant.

    I'm not sure you should be so worried about bad input. Just handle an out of memory exception somewhere high up in your app (std::bad_alloc I think). Otherwise, don't worry about the size of your container, whatever type you use.

  15. #15
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Quote Originally Posted by Daved
    I don't think it would matter much in this instance. Either way there will be some number that will cause the program to run out of memory. The OP must be referring to dynamic arrays, since static arrays must be sized with a compile time constant.
    Ah, but it would. You see, unless he was planning on allocating a new dynamic array every time he adds an element and transferring the old array to that before deleting, I'm assuming he'll be expecting a constant size for his array by the end-user during runtime. Now, where declaring a dynamic array of an enormous size could cause system instability, if he used containers, he could simply take note of the number entered. Keep accepting elements into his container until it's size reaches a "dangerous" limit, then swap it out to a swap file when it gets any larger. You see what I'm saying. I'm a bit tired so I might not be typing clearly, but I think that made sense.
    Sent from my iPadŽ

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Code review
    By Elysia in forum C++ Programming
    Replies: 71
    Last Post: 05-13-2008, 09:42 PM
  2. Need Help Please
    By YouShallNotPass in forum C++ Programming
    Replies: 3
    Last Post: 08-22-2006, 11:22 AM
  3. Converted from Dev-C++ 4 to Dev-C++ 5
    By Wraithan in forum C++ Programming
    Replies: 8
    Last Post: 12-03-2005, 07:45 AM
  4. Can't Find Conio.h?
    By drdroid in forum C++ Programming
    Replies: 27
    Last Post: 09-26-2002, 04:24 AM
  5. How do you search & sort an array?
    By sketchit in forum C Programming
    Replies: 30
    Last Post: 11-03-2001, 05:26 PM