I'm trying to understand what's going on under the hood of c conversions, and different types promotions and comparing stuff and all of this.
union myUnion{
int intVal;
float floatVal;};
if (m.floatVal == m.intVal)
{
cout << "BINGO!";
}
if (*ptrInt == *ptrInt2)
{
cout << "BINGO!" << endl << *ptrInt << endl << *ptrInt2;
}
The first if statement is evaluated to false and the second if statement to true.
How c compiler interprets this values m.floatVal, m.intVal. I'm mean what's going on down there, into assembly, because that's going to be run on the CPU.
Moreover m.floatVal, m.intVal gets evaluated different values depending on which variable I initialised first.
m.floatVal = 3; first gets something
m.intVal = 3; first gets something else.
In the end there is the same value there!?!?!?!?!?!?
Second example:
char minstogo = 0x98;
if (minstogo <= 7) {
cout << "BEAST!";
} beast is printed
char minstogo = 0x98;
if ((unsigned char)minstogo <= 7) {
cout << "BEAST!";
} nothing is printed
char minstogo = 0x98;
if (minstogo <= (unsigned char)7) {
cout << "BEAST!";
} beast is printed
How the compiler interprets this mess and what is going on down the assembly?
Third example:
How is a float converted to an int? Who the bits are all remapped?
Thank you so much guys! Thank you.
First example:
union myUnion{
int intVal;
float floatVal;};
if (m.floatVal == m.intVal)
{
cout << "BINGO!";
}
This is undefined behaviour in c++. Having written to intVal, reading floatVal is undefined behaviour. Having written to floatVal, reading intVal is undefined behaviour.
Related
I am working on below code:
#include<iostream>
#include<stdio.h>
using namespace std;
main() {
unsigned char a;
a=1;
printf("%d", a);
cout<<a;
}
It is printing 1 and some garbage.
Why cout is behaving so?
cout << a is printing a value which appears to be garbage to you. It is not garbage actually. It is just a non-printable ASCII character which is getting printed anyway. Note that ASCII character corresponding to 1 is non-printable. You can check whether a is printable or not using, std::isprint as:
std::cout << std::isprint(a) << std::endl;
It will print 0 (read: false) indicating the character is non-printable
--
Anyway, if you want your cout to print 1 also, then cast a to this:
cout << static_cast<unsigned>(a) << std::endl;
I had a similar issue here that I've long forgotten about. The resolution to this problem with iostream's cout can be done like this:
#include<iostream>
#include<stdio.h>
main() {
unsigned char a;
a=1;
printf("%d", a);
std::cout<< +a << std::endl;
return 0;
}
instead of casting it back to another type if you want cout to print the unsigned char value as opposed to the ascii character. You need to promote it.
If you noticed all I did was add a + before the unsigned char. This is unary addition that will promote the unsigned char to give you the actual number representation.
User Baum mit Augen is responsible for reminding me of this solution.
You need to typecast a as integer as cout<< (int)(a);. With this you will observe 1 on the output. With cout << a;, the print will be SOH (Start of Heading) corresponding to ascii value of 1 which can't be printed and hence, some special character is observed.
EDIT:
To be more accurate, the cout statement should be cout << static_cast<unsigned>(a) as Nawaz has mentioned.
The C compiler has its own way of defining the type of the printed output, because you can specify the type of the output.
Ex:
uint8_t c = 100;
printf("%d",c);
so you can also print c as an int by %d, or char %c, string %s or a hex value %x.
Where C++ has its own way too, the cout prints the 8-bit values as a char by default. So, you have to use specifiers with the output argument.
You can either use:
a + before the name of the output argument
uint8_t data_byte = 100;
cout << "val: " << +data_byte << endl;
use a function cast unsigned(var); like,
uint8_t data_byte = 100;
cout << "val: " << unsigned(data_byte) << endl;
printf("%u",a);
its so simple try it
When I run this function, It gives me a 2 warning for setw(*torPtr - *harePtr) and setw(*harePtr - *torPtr)
It said :
Arithmetic overflow: Using operator '-' on a 4-byte value and then casting the result to an 8-byte value. Cast the value to the wider type before calling operator '-' to avoid overflow (io.2).
How can I fix this please?
void Posi(const int* const tPtr,const int* const hPtr)
{
if (*hPtr == *tPtr) {
cout <<setw(*hPtr) << "bang!" << '\a';
}
else if (*hPtr < *tPtr) {
cout << setw(*hPtr) << 'H' << setw(*tPtr - *hPtr) << 'A';
}
else {
cout << setw(*tPtr) << 'T' << setw(*hPtr - *tPtr) << 'B';
}
}
When using Visual Studio, I get this error as well.
After looking into setw that I linked from #include <iomanip>, I found that setw is provided with a parameter streamsize which is actually a long long.
The resulting problem seems to be that you are trying to cast the arithmetic result of two int (with a size of 4 bytes) to a long long (with a size of 8 bytes) to conform to the definition of streamsize in setw.
An overflow caused by an arithmetic operation would not yield correct results.
If you want to learn, how an overflow is caused, you could look at the following web-article https://www.cplusplus.com/articles/DE18T05o/.
To fix the problem, you will need to prevent the overflow from occuring, which can be achieved by casting the values to a larger data type. For example:
const long long value_cast = static_cast<long long>(*tPtr) - static_cast<long long>(*hPtr);
cout << setw(*hPtr) << 'H' << setw(value_cast) << 'A';
I hope that this answers your question. :)
Edit:
I changed the cast from c-style to static. Thank you for your contribution anastaciu!
I'm writing a C++ program that converts a decimal number to binary and hexadecimal.
The problem is that for some reason it concatenates the number "1875954912" to both representations every time.
I've tried a bunch of things - mainly changing up how the program calculates numArrayLength and the for-loop in my decToBase function, but I haven't been able to figure out why this happens yet.
The program is not complete by the way - it doesn't turn integers bigger than 9 into letters for the hex representation yet, but that's not my main concern right now.
Here is my code:
#include <iostream>
#include <cmath>
using namespace std;
int howManyBitsNeeded(int someNum, int base) {
int numOfDivisions = 0;
while (someNum != 0) {
someNum = floor(someNum / base);
numOfDivisions += 1;
}
return numOfDivisions;
}
int decToBase(int someNum, int base) {
int bitsNeeded = howManyBitsNeeded(someNum,base);
int numArrayLength = bitsNeeded;
int numArray[bitsNeeded];
while (bitsNeeded > 0) {
numArray[bitsNeeded] = (someNum % base);
someNum = floor(someNum / base);
bitsNeeded -= 1;
}
for (int k = (numArrayLength-1); k >= 0; --k) {
cout << numArray[(numArrayLength - k)];
}
}
int main() {
int inpNum;
cout << "Enter your number: ";
cin >> inpNum;
cout << "Binary representation: " << decToBase(inpNum,2) << endl;
cout << "Hexadecimal representation: " << decToBase(inpNum,16);
return 0;
}
And here's what the output looks like:
Enter your number: 25
Binary representation: 110011875954912
Hexadecimal representation: 191875954912
Any help would be greatly appreciated!
Your decToBase is declared as returning an int, but it doesn't actually return anything. Your compiler should warn you about this. Since you're not returning anything here, change its return type to void. Then instead of trying to print its return value, simply call the function without printing it:
std::cout << "Binary representation: ";
decToBase(inpNum, 2); // this already prints the number, no need to pass it to std::cout
std::cout << endl;
std::cout << "Hexadecimal representation: ";
decToBase(inpNum, 16);
std::cout << std::endl;
Or of course you can change the function to return the string that you want to print instead of printing it inside the function.
Also, there's an issue here:
int numArray[bitsNeeded];
This is out of range when you try to access it here:
while (bitsNeeded > 0) {
numArray[bitsNeeded] = (someNum % base);
And also later when you try to print it. To get rid of this off by one error, you have to change this to
numArray[bitsNeeded-1] = (someNum % base);
And in the output change it to
cout << numArray[(numArrayLength - k -1)];
And while you're at it, instead of having it as a VLA (which isn't part of C++ and only works if the compiler tolerates it), I would recommend a vector:
std::vector<int> numArray(bitsNeeded+1); // include <vector> for this to work
Furthermore, note that integer division is already truncated, so unless you plan to support negative numbers later on, you can silence a warning about implicit double to int conversion by changing this:
someNum = floor(someNum / base);
To this:
someNum /= base;
I am working on below code:
#include<iostream>
#include<stdio.h>
using namespace std;
main() {
unsigned char a;
a=1;
printf("%d", a);
cout<<a;
}
It is printing 1 and some garbage.
Why cout is behaving so?
cout << a is printing a value which appears to be garbage to you. It is not garbage actually. It is just a non-printable ASCII character which is getting printed anyway. Note that ASCII character corresponding to 1 is non-printable. You can check whether a is printable or not using, std::isprint as:
std::cout << std::isprint(a) << std::endl;
It will print 0 (read: false) indicating the character is non-printable
--
Anyway, if you want your cout to print 1 also, then cast a to this:
cout << static_cast<unsigned>(a) << std::endl;
I had a similar issue here that I've long forgotten about. The resolution to this problem with iostream's cout can be done like this:
#include<iostream>
#include<stdio.h>
main() {
unsigned char a;
a=1;
printf("%d", a);
std::cout<< +a << std::endl;
return 0;
}
instead of casting it back to another type if you want cout to print the unsigned char value as opposed to the ascii character. You need to promote it.
If you noticed all I did was add a + before the unsigned char. This is unary addition that will promote the unsigned char to give you the actual number representation.
User Baum mit Augen is responsible for reminding me of this solution.
You need to typecast a as integer as cout<< (int)(a);. With this you will observe 1 on the output. With cout << a;, the print will be SOH (Start of Heading) corresponding to ascii value of 1 which can't be printed and hence, some special character is observed.
EDIT:
To be more accurate, the cout statement should be cout << static_cast<unsigned>(a) as Nawaz has mentioned.
The C compiler has its own way of defining the type of the printed output, because you can specify the type of the output.
Ex:
uint8_t c = 100;
printf("%d",c);
so you can also print c as an int by %d, or char %c, string %s or a hex value %x.
Where C++ has its own way too, the cout prints the 8-bit values as a char by default. So, you have to use specifiers with the output argument.
You can either use:
a + before the name of the output argument
uint8_t data_byte = 100;
cout << "val: " << +data_byte << endl;
use a function cast unsigned(var); like,
uint8_t data_byte = 100;
cout << "val: " << unsigned(data_byte) << endl;
printf("%u",a);
its so simple try it
While reading "C++ Primer Plus 5th edition", I saw this piece of code:
cin.get(ch);
++ch;
cout << ch;
So, this will lead to display the following character after ch. But, If I did it that way:
cin.get(ch);
cout << ch+1;
Now, cout will think ch is an int(try typecasting). So, why cout does so?
And why if I added 1 to a char it will produce a number?. And why there's a difference between:
ch++, and ch + 1.
The reason this occurs is the type of the literal 1 is int. When you add an int and a char you get an int, but when you increment a char, it remains a char.
Try this:
#include <iostream>
void print_type(char)
{
std::cout << "char\n";
}
void print_type(int)
{
std::cout << "int\n";
}
void print_type(long)
{
std::cout << "long\n";
}
int main()
{
char c = 1;
int i = 1;
long l = 1;
print_type(c); // prints "char"
print_type(i); // prints "int"
print_type(l); // prints "long"
print_type(c+i); // prints "int"
print_type(l+i); // prints "long"
print_type(c+l); // prints "long"
print_type(c++); // prints "char"
return 0;
}
Please note - this is the answe to the original question, which has since been edited.
Now, cout will think ch is an int(try
typecasting).
No it won't. It is not possible to change the type of a variable in C++.
++ch;
increments whatever is in ch.
ch + 1;
takes the value (contents) of ch, adds 1 to it and discards the result. Whatever is in ch is unchanged.
The statement ++ch; increments ch whereas ch + 1; doesn't.
Also, rememeber that '++ch' will do the increment before actually running the statement it is in, so that is why it remains a char.
int i = 0;
cout << ++i << endl;
cout << i++ << endl;
// both will print out 1.