I can't understand why this loop prints "INFINITE". If the string length is 1, how can length()-2 result in a big integer?
for(int i=0;i<s.length()-2;i++)
{
cout<<"INFINITE"<<endl;
}
std::string.length() returns a size_t. This is an unsigned integer type. You are experiencing integer overflow. In pseudocode:
0 - 1 = int.maxvalue
In your case specifically it is:
(size_t)1 - 2 = SIZE_MAX
where SIZE_MAX usually equals 2^32 - 1
std::string::length() returns a std::string::size_type.
std::string::size_type is specified to be the same type as allocator_traits<>::size_type (of the string's allocator).
This is specified to be an unsigned type.
Hence, the number will wrap (defined behaviour) and become huge. Precisely how huge will depend on the architecture.
You can test it on your architecture with this little program:
#include <limits>
#include <iostream>
#include <string>
#include <utility>
#include <iomanip>
int main() {
using size_type = std::string::size_type;
std::cout << "unsigned : " << std::boolalpha << std::is_unsigned<size_type>::value << std::endl;
std::cout << "size : " << std::numeric_limits<size_type>::digits << " bits" << std::endl;
std::cout << "npos : " << std::hex << std::string::npos << std::endl;
}
in the case of apple x64:
unsigned : true
size : 64 bits
npos : ffffffffffffffff
Related
For example 14.2 is not an integer but 14.0 is an integer in a mathematical perspective. What I've tried to do is the following, let n be a long double, so to check if it's an integer I compared it to its integer form:
if (n == (int) n)
{
// n is an integer
}
It all looks perfect but when I applied it, it didn't work, and when i debugged the program I discovered that the long double number is never a whole number; it's not 14.0 instead it's 14.0000000000000000000002, the last 2 is added by the compiler.
Does someone know how to fix it?
The cleanest approach is to use floor() and not concern yourself with casting to integer types which makes the false assumption that there will be no overflow in converting a floating-point value to integer.
For large floats that's obviously not true.
#include <iostream>
#include <cmath> // This is where the overloaded versions of floor() are.
bool is_whole(double d){
return d==floor(d);
}
int main() {
double x{14.0};
double y{14.2};
double z{-173.5};
std::cout << is_whole(14.0) << '\n';
std::cout << is_whole(14.2) << '\n';
std::cout << is_whole(-123.4) << '\n';
std::cout << is_whole(-120394794.0) << '\n';
std::cout << is_whole(-120394794.44) << '\n';
std::cout << is_whole(3681726.0) << '\n';
return 0;
}
Expected Output:
1
0
0
1
0
1
The code successfully compiles it but I can't understand why, for certain values of number, the program crashes and for other values it doesn't. Could someone explain the behavior of adding a long int with a char* that the compiler uses?
#include <iostream>
int main()
{
long int number=255;
std::cout<< "Value 1 : " << std::flush << ("" + number) << std::flush << std::endl;
number=15155;
std::cout<< "Value 2 : " << std::flush << ("" + number) << std::flush << std::endl;
return 0;
}
Test results:
Value 1 : >
Value 2 : Segmentation fault
Note: I'm not looking for a solution on how to add a string with a number.
In C++, "" is a const char[1] array, which decays into a const char* pointer to the first element of the array (in this case, the string literal's '\0' nul terminator).
Adding an integer to a pointer performs pointer arithmetic, which will advance the memory address in the pointer by the specified number of elements of the type the pointer is declared as (in this case, char).
So, in your example, ... << ("" + number) << ... is equivalent to ... << &""[number] << ..., or more generically:
const char *ptr = &""[0];
ptr = reinterpret_cast<const char*>(
reinterpret_cast<const uintptr_t>(ptr)
+ (number * sizeof(char))
);
... << ptr << ...
Which means you are going out of bounds of the array when number is any value other than 0, thus your code has undefined behavior and anything could happen when operator<< tries to dereference the invalid pointer you give it.
Unlike in many scripting languages, ("" + number) is not the correct way to convert an integer to a string in C++. You need to use an explicit conversion function instead, such as std::to_string(), eg:
#include <iostream>
#include <string>
int main()
{
long int number = 255;
std::cout << "Value 1 : " << std::flush << std::to_string(number) << std::flush << std::endl;
number = 15155;
std::cout << "Value 2 : " << std::flush << std::to_string(number) << std::flush << std::endl;
return 0;
}
Or, you can simply let std::ostream::operator<< handle that conversion for you, eg:
#include <iostream>
int main()
{
long int number = 255;
std::cout<< "Value 1 : " << std::flush << number << std::flush << std::endl;
number = 15155;
std::cout<< "Value 2 : " << std::flush << number << std::flush << std::endl;
return 0;
}
Pointer arithmetic is the culprit.
A const char* is accepted by operator<<, but will not point to a valid memory address in your example.
If you switch on -Wall, you will see a compiler warning about that:
main.cpp: In function 'int main()':
main.cpp:6:59: warning: array subscript 255 is outside array bounds of 'const char [1]' [-Warray-bounds]
6 | std::cout<< "Value 1 : " << std::flush << ("" + number) << std::flush << std::endl;
| ^
main.cpp:8:59: warning: array subscript 15155 is outside array bounds of 'const char [1]' [-Warray-bounds]
8 | std::cout<< "Value 2 : " << std::flush << ("" + number) << std::flush << std::endl;
| ^
Value 1 : q
Live Demo
The code successfully compiles it but I can't understand why, for certain values of number, the program crashes and for other values it doesn't. Could someone explain the behavior of adding a long int with a char* that the compiler uses?
#include <iostream>
int main()
{
long int number=255;
std::cout<< "Value 1 : " << std::flush << ("" + number) << std::flush << std::endl;
number=15155;
std::cout<< "Value 2 : " << std::flush << ("" + number) << std::flush << std::endl;
return 0;
}
Test results:
Value 1 : >
Value 2 : Segmentation fault
Note: I'm not looking for a solution on how to add a string with a number.
In C++, "" is a const char[1] array, which decays into a const char* pointer to the first element of the array (in this case, the string literal's '\0' nul terminator).
Adding an integer to a pointer performs pointer arithmetic, which will advance the memory address in the pointer by the specified number of elements of the type the pointer is declared as (in this case, char).
So, in your example, ... << ("" + number) << ... is equivalent to ... << &""[number] << ..., or more generically:
const char *ptr = &""[0];
ptr = reinterpret_cast<const char*>(
reinterpret_cast<const uintptr_t>(ptr)
+ (number * sizeof(char))
);
... << ptr << ...
Which means you are going out of bounds of the array when number is any value other than 0, thus your code has undefined behavior and anything could happen when operator<< tries to dereference the invalid pointer you give it.
Unlike in many scripting languages, ("" + number) is not the correct way to convert an integer to a string in C++. You need to use an explicit conversion function instead, such as std::to_string(), eg:
#include <iostream>
#include <string>
int main()
{
long int number = 255;
std::cout << "Value 1 : " << std::flush << std::to_string(number) << std::flush << std::endl;
number = 15155;
std::cout << "Value 2 : " << std::flush << std::to_string(number) << std::flush << std::endl;
return 0;
}
Or, you can simply let std::ostream::operator<< handle that conversion for you, eg:
#include <iostream>
int main()
{
long int number = 255;
std::cout<< "Value 1 : " << std::flush << number << std::flush << std::endl;
number = 15155;
std::cout<< "Value 2 : " << std::flush << number << std::flush << std::endl;
return 0;
}
Pointer arithmetic is the culprit.
A const char* is accepted by operator<<, but will not point to a valid memory address in your example.
If you switch on -Wall, you will see a compiler warning about that:
main.cpp: In function 'int main()':
main.cpp:6:59: warning: array subscript 255 is outside array bounds of 'const char [1]' [-Warray-bounds]
6 | std::cout<< "Value 1 : " << std::flush << ("" + number) << std::flush << std::endl;
| ^
main.cpp:8:59: warning: array subscript 15155 is outside array bounds of 'const char [1]' [-Warray-bounds]
8 | std::cout<< "Value 2 : " << std::flush << ("" + number) << std::flush << std::endl;
| ^
Value 1 : q
Live Demo
I have a bitset in which I need to store a # of randomly generated integers (store its bit representation of course). So, the thing is that I am confuse on how to do that.
i.e suppose that I generate the integers (all unsigned int) 8, 15 , 20, one at a time. How can I store the recently generated integer in my existing bit set.
Say that I start by generating "8" and store in the bitset, then I generate "15" and store it in the bitset.
I don't know or don't understand how to store those values within the bitset.
Note: I know in advance the size of the bitset, the size is based on the number of integers that I am going to generate, and that I know too. So, at the end what I need is a bitset with all the bits set matching the bits of all the generated integers.
I'll Appreciate your help.
How can I store the recently generated integer in my existing bit set.
You can generate a temporary bitset form the integer and then assign values between the two bitsets.
Example program:
#include <iostream>
#include <bitset>
#include <cstdlib>
int main()
{
const int size = sizeof(int)*8;
std::bitset<2*size> res;
std::bitset<size> res1(rand());
std::bitset<size> res2(rand());
for ( size_t i = 0; i < size; ++i )
{
res[i] = res1[i];
res[size+i] = res2[i];
}
std::cout << "res1: " << res1 << std::endl;
std::cout << "res2: " << res2 << std::endl;
std::cout << "res: " << res << std::endl;
return 0;
}
Output:
res1: 01101011100010110100010101100111
res2: 00110010011110110010001111000110
res: 0011001001111011001000111100011001101011100010110100010101100111
Update
A function to set the bitset values given an integer can be used to avoid the cost of creating temporary bitsets.
#include <iostream>
#include <bitset>
#include <cstdlib>
#include <climits>
const int size = sizeof(int)*8;
void setBitsetValue(std::bitset<2*size>& res,
int num,
size_t bitsetIndex,
size_t numIndex)
{
if ( numIndex < size )
{
res[bitsetIndex] = (num >> numIndex) & 0x1;
setBitsetValue(res, num, bitsetIndex+1, numIndex+1);
}
}
int main()
{
std::bitset<2*size> res;
int num1 = rand()%INT_MAX;
int num2 = rand()%INT_MAX;
std::bitset<size> res1(num1);
std::bitset<size> res2(num2);
std::cout << "res1: " << res1 << std::endl;
std::cout << "res2: " << res2 << std::endl;
setBitsetValue(res, num1, 0, 0);
setBitsetValue(res, num2, size, 0);
std::cout << "res: " << res << std::endl;
return 0;
}
This question already has answers here:
maximum value of int
(7 answers)
Closed 9 years ago.
I thought that unsigned int max possible value is 65535 ( in C++ ) but I created a programm which can use an int which is equal with 100000 for example. Is it safe to use int with values up to 10000000 or the program may crash? In that case is long the only solution?
Thank you for your time!
Use std::numeric_limits<unsigned int>::max() to know for certain what this value is.
Please check the code below for limits:
#include <iostream> // std::cout
#include <limits> // std::numeric_limits
int main () {
std::cout << "Minimum value for int: " << std::numeric_limits<int>::min() << '\n';
std::cout << "Maximum value for int: " << std::numeric_limits<int>::max() << '\n';
std::cout << "int is signed: " << std::numeric_limits<int>::is_signed << '\n';
std::cout << "Non-sign bits in int: " << std::numeric_limits<int>::digits << '\n';
std::cout << "int has infinity: " << std::numeric_limits<int>::has_infinity << '\n';
return 0;
}
INT_MAX is implementation defined. That means it's up to your compiler vendor to decide, as long as it's no less than 32767, and greater or equal to a short. You can use the climits definitions to discover your implementation's limits:
#include <iostream>
#include <climits>
int main () {
std::cout << INT_MAX << std::endl;
return 0;
}
On my installation of gcc/g++ v4.8.1 targeting x86_64-linux-gnu, this snippet produces:
2147483647
And as has been mentioned in the followup replies to this answer, you may (and probably should) use the more semantically proper (for C++) method:
#include <iostream>
#include <limits>
int main () {
std::cout << std::numeric_limits<int>::max() << std::endl;
return 0;
}
...which ought to produce the same output.