简体   繁体   中英

What does the unsigned keyword do here?

I wrote some C++ code to show ASCII characters on a console which I found in a book i was reading. The code looked like this:

#include <iostream>

using namespace std;

int main()  
{  
    for (unsigned char i = 32; i<128; i++)  
       cout << i;  
    int response;  
    cin >> response;  
    return 0;  
}

When I take away the unsigned keyword and use signed instead, the results become infinite and the PC beeps until I shut off the executable file. But when I use an int i variable instead I don't need to unsign the variable. Why is that?

unsigned simply means that the number won't become negative. Yeah, number, because a char really is just an 8-bit integer.

So when unsigned , every bit is used in the non-negative range, which will go from 0 to 255. When you leave out and use a signed (default) char, the range will go from -128 to 127, thus it will always be less than 128 and go into an infinite loop.

The beep you hear is due to the char of value 7 being "printed".


An int , on the other hand, even when signed goes all the way from -2.147... billions to +2.147 billions, so it will iterate normally until reaching 128 and stopping.

The signed char type ranges from -128 through +127 .

Therefore, i<128 can never be false, so your loop will never terminate.

Instead, 127 + 1 as a signed char will wrap around to -128 (because it will set the sign bit), which will then continue through the loop a second time.

This second iteration will include every character, including \\a (bell), which beeps when printed.

Unsigned means that the variable will only contain positive values, which means that they have can contain larger positive numbers. The range of unsigned char is typically 0 to 255, and the range of a signed char is -128 to +127. This can vary on different hardware (but won't on most hardware you are likely to come across).

When a variable is incremented from it's maximum value, it overflows. What happens to the variable depends on whether it is unsigned or not. Unsigned types are guaranteed to become 0, while signed types the behaviour is undefined. On most systems that I've seen the variable wraps around to the minimum value (in this case -128), but you can't rely on this behaviour.

What this means is that the variable will never reach 128, so the loop will continue forever.

If you goto this page and look at fundamental data types you can see the typical ranges of signed vs unsigned of all fundamental types: http://www.cplusplus.com/doc/tutorial/variables/

signed char range is from -128 to +127, so it will always be less than 128

When you do

signed i=127;
i++;

i will usually be -128 (but you can't count with this behaviour)

unsigned char range is from 0 to 255

Not all ASCII characters are printable! It is nonsense to print them.

The types signed char and unsigned char are distinct integer types. As the names imply, one is a signed type (ie, can represent negative values) and the other is an unsigned type (ie, .can represent only non-negative values).

The type char , with no signed or unsigned prefix, is yet another distinct type. It has the same representation and range as either signed char or unsigned char ; which one it is is implementation-defined. (A subtle point: they're still three distinct types even though two of them have identical characteristics.)

For typical implementations, all three of these types are 8 bits, and signed types are represented using two's-complement, giving signed char a range of -128 .. +127 and unsigned char a range of 0 .. +255.

On your implementation, it seems that plain char is signed (that's very common). So if i is of type char , then i < 128 is always true, and you have an infinite loop. And incrementing a char or signed char object past its maximum value actually has undefined behavior, but typically it wraps around from the maximum value to the minimum value, which is what you're seeing. (The beep is probably produced when the character being printed is \\007 , the ASCII BEL character; either that, or you're sending control characters that mess up your terminal.)

Making i an unsigned char gives it a range from 0 to 255, and your loop stops when it reaches 128. (Incrementing a value of an unsigned type past its maximum value is well defined, but you don't do that anyway.)

int is always a signed type, and its range is required by the language to be at least -32767 .. +32767. These days, it's commonly 32 bits, with a range of -2147483648 .. +2147483647. But even with the minimum required range, it's more than big enough for your loop.

A signed char (at least in a typcical case) can only represent values from -128 to +127. Since it can never have the value 128, your loop runs forever.

Officially, when it has the value 127 and you increment, the result is undefined behavior. In reality, on almost any typical machine (anything using 2's complement) when it has the value 127 and you increment, it'll wrap around to -128, increment back up to 127, wrap around to -128 and go through the whole cycle again.

With an unsigned char, you get values from 0 to (at least) 255, so when you get to 127 and increment, the value goes to 128, ending the loop as expected.

Likewise, an int is required to have a range from at least -32767 to +32767. Therefore, when it has a value of 127, and you increment, the result will be 128, as you'd normally expect.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM