Casting from size_t to char and around - c++

I'm making the transition from C to C++11 now and I try to learn more about casting.
At the end of this question you see a small program which asked a number as input and then shows it as number and as character. Then it is cast to a char, and after that I cast it back to a size_t.
When I give 200 as input, the first cout prints 200, but the second cout prints 18446744073709551560.
How do I made it to print 200 again? Do I use the wrong cast? I have already tried different cast as dynamic and reintepret.
#include<iostream>
using namespace std;
int main(){
size_t value;
cout << "Give a number between 32 and 255: ";
cin >> value;
cout << "unsigned value: " << value << ", as character: `" << static_cast<char>(value) << "\'\n";
char ch = static_cast<char>(value);
cout << "unsigned value: " << static_cast<size_t>(ch) << ", as character: `" << ch << "\'\n";
}

size_t is unsigned, plain char's signed-ness is implementation-defined.
Casting 200 to a signed char will yield a negative result as 200 is larger than CHAR_MAX which is 127 for the most common situation, an 8-bit char. (Advanced note - this conversion is also implementation-defined but for all practical purposes you can assume a negative result; in fact usually -56).
Casting that negative value back to an unsigned (but wider) integer type will yield a rather large value, because unsigned arithmetic wraps around.
You might cast the value to an unsigned char first (yielding the expected small positive value), then cast that the wider unsigned type.
Most compilers have a switch that lets you toggle plain char over to unsigned so you could experiment with that. When you come to write portable code, try to write code that will work correctly in both cases!

Related

Is there any char data type alternative ( 1-byte value ) to represent numeric values?

I've this issue:
#include <iostream>
int main() {
unsigned char little_number_from_0_to_255 = 0;
std::cout << "How old are you (for example)? _";
std::cin >> little_number_from_0_to_255;
std::cout << "You are " << little_number_from_0_to_255 << " year/s old.";
}
In brief,
even if in this case what follows would'nt care much,
i'd like to avoid the waste of 1 byte (if compared to a short int type) for each variable i need to store when its value is so tiny,
but in all my attempts the un/signed char type variable is always interpreted as the ASCII representation of the first digit of the number I input the un/signed into.
Is there in C++ any good way to have a 1 byte data type, the value of could be only numeric (with all the arithmetic etc., like un/signed char) but without having to deal with the automatic ASCII representation (unlike un/signed char)?
If not, how could i "circumvent" the problem?
Is there a way to avoid that, even if I say that I'm 61, in the variable there will be 54 (decimal) and i will realize that i'm a liar 'cause in reality i'm only 6?
A way to say the computer that it has to grab the whole number and that it hasn't to look only at the first character input?
--I've already read of '+' just before the char variable, but this works only for output, and isn't my case.
Is there in C++ any good way to have a 1 byte data type, the value of could be only numeric (with all the arithmetic etc., like un/signed char) but without having to deal with the automatic ASCII representation (unlike un/signed char)?
You could define a wrapper class that stores a single byte integer type such as std::int8_t as a member, and implicitly converts to a non-character integer type such as int. Whether this is "good" is subjective and depends on use case.
If not, how could i "circumvent" the problem?
You can use an intermediate variable of non-character integer type when dealing with character streams:
std::uint8_t little_number_from_0_to_255 = 0;
// input
unsigned input;
std::cout << "How old are you (for example)? _";
std::cin >> input;
little_number_from_0_to_255 = input;
// output
unsigned output = little_number_from_0_to_255
std::cout << "You are " << output << " year/s old.";

Is there an alternative to char for storing one byte numeric values?

A char stores a numeric value from 0 to 255. But there seems to also be an implication that this type should be printed as a letter rather than a number by default.
This code produces 22:
int Bits = 0xE250;
signed int Test = ((Bits & 0x3F00) >> 8);
std::cout << "Test: " << Test <<std::endl; // 22
But I don't need Test to be 4 bytes long. One byte is enough. But if I do this:
int Bits = 0xE250;
signed char Test = ((Bits & 0x3F00) >> 8);
std::cout << "Test: " << Test <<std::endl; // "
I get " (a double quote symbol). Because char doesn't just make it an 8 bit variable, it also says, "this number represents a character".
Is there some way to specify a variable that is 8 bits long, like char, but also says, "this is meant as a number"?
I know I can cast or convert char, but I'd like to just use a number type to begin with. It there a better choice? Is it better to use short int even though it's twice the size needed?
cast your character variable to int before printing
signed char Test = ((Bits & 0x3F00) >> 8);
std::cout << "Test: " <<(int) Test <<std::endl;

How can I capture an unsigned value without casting?

How can I capture an unsigned value without casting?
I am writing a simple program to calculate the LCF and the GCD of an array of numbers. In order to properly calculate them, the numbers should be always positive intergers, for I which chose the type "unsigned long long int". However, I still did not find a way to prevent the user to enter a negative value without casting.
Whenever I use std::cin >> variable, the program allows the user to enter a negative number. In case of unsigned values, the number will be the range-minus-value of the size of type. In case of unsigned short interger, if a user enters -5, the value stored in the variable will be 65.531.
Here is the part of the code I am trying to improve:
#include<iostream>
#include<stdlib.h>
using namespace std;
typedef unsigned long long int ulli;
/* many lines of code, variables already declared */
// array_list_of_numbers is of type UNsigned long long int
// var_verify_if_negative is of type signed long long int
cout << "Please inform the numbers." << endl;
for ( iterador1 = 0 ; iterador1 < size_of_the_list ; ++iterador1){
cout << "Please, inform number "<< iterador1+1 << ": ";
cin >> var_verify_if_negative;
while (var_verify_if_negative <= 0){
cout << "Number must be equal or greater than 1!" << endl;
cout << "Try again: ";
cin >> var_verify_if_negative;
/*end while*/}
array_list_of_numbers[iterador1] = (ulli)var_verify_if_negative; // << here is the casting
/*end for*/}
However, if I use casting of a signed variable, there is no point of using unsigned data type at all. It would be better to declare the variables already as signed and perform the check.
The original code was:
cout << "Please inform the numbers." << endl;
for ( iterador1 = 0 ; iterador1 < size_of_the_list ; ++iterador1){
cout << "Please, inform number "<< iterador1+1 << ": ";
cin >> array_list_of_numbers[iterador1];
/*end for*/}
Which allows wrong input.
How can I test if a user entered a signed value using std::cin ?
Why not simply read a (signed) long and refuse it when its negative and use it otherwise ?
If you really need the full range of an unsigned long you would need to read a string first, check if it starts with a '-' (and refuse) and convert to unsigned long otherwise.
Unfortunately, there is no specific extractor which would refuse signed integers for standard stream, instead, signed integer is converted to unsigned value (which is actually undefined behavior for negative numbers).
However, your whole approach is somewhat flawed. If you want to disallow numbers which are less than 0, the best you can do is to actually accept signed integers, and than check the number to be greater than zero and report error (and refuse the input) when it is not.
The best case scenario would have been for the stream extractor to report failure when a negative number is entered when the expected type is an unsigned type.
unsigned int num;
while ( !(in >> num) )
{
std::cerr << "Wrong input. Try again...";
}
However, the standard specifies that it's OK to enter negative number even when the expected type is an unsigned type.
When the type is an unsigned type, the standard library uses the %u format specifier in the core conversion logic. From https://en.cppreference.com/w/cpp/locale/num_get/get:
If the type of v is unsigned, will use conversion specifier %u
Now, if you look at how the standard library deals with %u (https://en.cppreference.com/w/cpp/io/c/fscanf#Parameters), the conversion is performed by strtoul.
From strtoul documentation:
If the minus sign was part of the input sequence, the numeric value calculated from the sequence of digits is negated as if by unary minus in the result type, which applies unsigned integer wraparound rules.
Your best bet is to read into a signed type and make sure it is a non-negative number before proceeding to use it.

Why does int8_t and user input via cin shows strange result [duplicate]

This question already has answers here:
uint8_t can't be printed with cout
(8 answers)
Closed 8 years ago.
A tiny piece of code drives me crazy but hopefully you can prevent me from jumping out of the window. Look here:
#include <iostream>
#include <cstdint>
int main()
{
int8_t i = 65;
int8_t j;
std::cout << "i = " << i << std::endl; // the 'A' is ok, same as uchar
std::cout << "Now type in a value for j (use 65 again): " << std::endl;
std::cin >> j;
std::cout << "j = " << j << std::endl;
if (i != j)
std::cout << "What is going on here?????" << std::endl;
else
std::cout << "Everything ok." << std::endl;
return 0;
}
If I use int instead of int8_t everything ok. I need this as 8-bit unsigned integers, not bigger. And btw. with unsigned char it's the same behaviour - of course - as with int8_t.
Anyone with a hint?
int8_t is a typedef for an integer type with the required characteristics: pure 2's-complement representation, no padding bits, size of exactly 8 bits.
For most (perhaps all) compilers, that means it's going to be a typedef for signed char.(Because of a quirk in the definition of the term signed integer type, it cannot be a typedef for plain char, even if char happens to be signed).
The >> operator treats character types specially. Reading a character reads a single input character, not sequence of characters representing some integer value in decimal. So if the next input character is '0', the value read will be the character value '0', which is probably 48.
Since a typedef creates an alias for an existing type, not a new distinct type, there's no way for the >> operator to know that you want to treat int8_t as an integer type rather than as a character type.
The problem is that in most implementations there is no 8-bit integer type that's not a character type.
The only workaround is to read into an int variable and then convert to int8_t (with range checks if you need them).
Incidentally, int8_t is a signed type; the corresponding unsigned type is uint8_t, which has a range of 0..255.
(One more consideration: if CHAR_BIT > 8, which is permitted by the standard, then neither int8_t nor uint8_t will be defined at all.)
int8_t and uint8_t are almost certainly character types (Are int8_t and uint8_t intended to behave like a character?) so std::cin >> j will read a single character from stdin and interpret it as a character, not as a number.
int8_t is likely the same as char, which means cin >> j will simply read a single character ('6') from input and store it in j.
int8_t is defined as a typedef name for signed char. So operator >> used with an object of type int8_t behaves the same way as it would be used for an object of type signed char
The _t types aren't first class types, they are typedef aliases the observe certain constraints, e.g. int8_t is a type that can store a signed, 8-bit value.
On most systems, this will mean they are typedefd to char. And because they are a typedef and not a first-class type, you are invoking cin.operator<<(char) and cin.operator>>(char).
When you input "65", cin.operator>>(char) consumes the '6' and places it's ascii value, 54, into variable j.
To work around this you'll need to use a different type, possibly the easiest method being just to use a larger integer type and apply constraints and then cast down:
int8_t fetchInt8(const char* prompt) {
int in = 0;
for ( ; ; ) { // endless loop.
std::cout << prompt << ": ";
std::cin >> in;
if (in >= std::numeric_limits<int8_t>::min()
&& in <= std::numeric_limits<int8_t>::max()) {
std::cout << "You entered: " << in << '\n';
// exit the loop
break;
}
std::cerr << "Error: Invalid number for an int8\n";
}
return static_cast<int8_t>(in);
}
Note that int8_t is signed, which means it stores -128 thru +127. If you want only positive values, use the uint8_t type.

Why is std::cout not printing the correct value for my int8_t number?

I have something like:
int8_t value;
value = -27;
std::cout << value << std::endl;
When I run my program I get a wrong random value of <E5> outputted to the screen, but when I run the program in gdb and use p value it prints out -27, which is the correct value. Does anyone have any ideas?
Because int8_t is the same as signed char, and char is not treated as a number by the stream. Cast into e.g. int16_t
std::cout << static_cast<int16_t>(value) << std::endl;
and you'll get the correct result.
This is because int8_t is synonymous to signed char.
So the value will be shown as a char value.
To force int display you could use
std::cout << (int) 'a' << std::endl;
This will work, as long as you don't require special formatting, e.g.
std::cout << std::hex << (int) 'a' << std::endl;
In that case you'll get artifacts from the widened size, especially if the char value is negative (you'd get FFFFFFFF or FFFF1 for (int)(int8_t)-1 instead of FF)
Edit see also this very readable writeup that goes into more detail and offers more strategies to 'deal' with this: http://blog.mezeske.com/?p=170
1 depending on architecture and compiler
Most probably int8_t is
typedef char int8_t
Therefore when you use stream out "value" the underlying type (a char) is printed.
One solution to get a "integer number" printed is to type cast value before streaming the int8_t:
std::cout << static_cast<int>(value) << std::endl;
It looks like it is printing out the value as a character - If you use 'char value;' instead, it prints the same thing. int8_t is from the C standard library, so it may be that cout is not prepared for it(or it is just typedefd to char).