Keyword "auto" near critical points [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How much is too much with C++0x auto keyword
I find using "auto" near critical points maybe cause some problems.
This is the example code:
#include <iostream>
#include <typeinfo>
#include <limits>
using std::cout;
using std::endl;
using std::numeric_limits;
using std::cerr;
int main() {
auto i = 2147483647 /* numeric_limits<int>::max() */ ;
cout << "The type of i is " << typeid(i).name() << endl;
int count = 0;
for (auto i = 2147483647;
i < 2147483657 /* numeric_limits<int>::max() + 10 */ ; ++i) {
cout << "i = " << i << " " << endl;
if (count > 30) {
cerr << "Too many loops." << endl;
break;
}
++count;
}
return 0;
}
The "auto" decides the type of "i" is integer, but the upper limit of integer is 2147483647, that's easily overflow.
That's the outputs on Ideone(gcc-4.5.1) and LWS(gcc-4.7.2). They're different: "i" remains 2147483647 in the loops on Ideone(gcc-4.5.1) and overflows on LWS(gcc-4.7.2). But none of them is the expecting result: 10 cycles, +1 every time.
Should I avoid to use "auto" near critical points? Or How I use "auto" appropriately here?
UPDATE: Someone says "Use auto everywhere you can." in this thread you tell me. I don't think that's quite right. Type "long long int" is more appropriate the type "int" here. I wonder where I can use "auto" safely, where can't.
UPDATE 2: The solution 4(b) of the article by Herb Sutter should have answered the question.

You should only rely on type deduction to work out the type of your variables if it's going to be correct. Here, the compiler makes the deduction that it's an int, which is right as far as the standard is concerned, but your specific problem requires another type with a larger range. When you use auto, you're saying "the compiler knows best", but the compiler doesn't always know everything.
You wouldn't use auto here, just as you wouldn't use int. You could make your literal have higher rank (stick L or LL after it - although they're not guaranteed to be any larger than your int) and then auto would deduce a larger integral type.
Not to mention that auto really saves you nothing in this case. auto is usually used to avoid typing long, ugly types or types that you don't know. In this case, the type is not long and ugly, and you do know it.

auto is just a syntactic sugar. It isn't a type, it just infers what type the right side is supposed to be and decides that variable's type by that.
If you give it literals, it will just infer the default type it is given by the compiler.
You just need to know what the actual type is.

An numeric literal (without the decimal point) is always int unless you explicitly change its type.
int x = 2147483657; // 2147483657 is treated as an int.
// If it does not fit tough it will be truncated
// according to standard rules.
long x = 2147483657L; // The L suffix tells the compiler to treat it as a long.
// Here you will get the correct value assuming long is larger than int.
In your case:
for(auto i = 2147483647;i < 2147483657;) // is not going to work as i is always
// an int and literal overflows.
// Try correct types:
for(auto i = 2147483647L; i < 2147483657L;++i) //Now it should work correctly.

You are expecting too much out of auto. Your expectation is that auto will automatically deduce the type which is best for the manipulation that you are going to perform on your variable. This is semantic analysis and compilers are not expected to do that (most often, they cannot). They can't look forward into the way you are going to use the variable you declare later on in your program.
The auto keyword only saves you from the burden of explicitly writing on the left the type of the expression appearing on the right, avoiding possible redundancy and all problems connected with it (what if the type of the expression on the right changes?)
This said, all other answers are correct: if you want your variable i not to overflow, you should assign to it a long long literal (using the LL postfix).

Related

Expecting warnings when casting enums to integers with overflow

We have a big C++ project where we rely on compiler warnings and Flexelint to identify potential programming errors. I was curious about how they will warn us once we accidentally try to cast an enum value to a narrower integer.
As suggested by Lint, we usually perform static casts from the enum to the integer. Lint doesn't like implicit casts. We usually cast to the exact type expected by the method.
I got interesting results, see this experiment:
#include <iostream>
#include <string>
#include <stdint.h>
void foo(uint8_t arg)
{
std::cout << static_cast<int>(arg) << std::endl;
}
enum Numbers
{
hundred = 100,
thousand = 1000,
};
int main()
{
std::cout << "start" << std::endl;
foo(static_cast<uint8_t>(hundred)); // 1) no compiler or lint warning
foo(static_cast<uint8_t>(thousand)); // 2) no compiler or lint warning
foo(static_cast<int>(thousand)); // 3) compiler and lint warning
foo(thousand); // 4) compiler and lint warning
std::cout << "end" << std::endl;
}
http://cpp.sh/5hpyz
First case is not a concern, just to mention the good case.
Interestingly, I only got compiler warnings in the latter two cases, when doing an implicit cast. The explicit cast in case 2) will truncate the value (output is 232 like the following two) but with no warning. Ok, the compiler is probably assuming I know what I'm doing here with my explicit cast to uint8_t. Fair enough.
I expected Lint to help me out here. I run this code in Gimpel's online Lint but didn't get any warnings either. Only in the latter two cases again, with this warning:
warning 569: loss of information (call) in implicit conversion from 'int' 1000 (10 bits) to 'uint8_t' (aka 'unsigned char') (8 bits)
Again, the explicit cast to uint8_t in case 2), that truncates my value, doesn't bother Lint at all.
Given a case where all values in an enum fit into the uint8_t. But in some future, we add bigger values (or say: more than 256 values in total), cast them and without noticing that this will truncate them and get unexpected results.
By default, I always cast to the target variable size (case 2) ). Given this experiment, I wonder if this is a wise approach. Shall I cast to the widest type and rely on implicit casts instead (case 3) )?
What's the right approach to get the expected warnings?
You could also write foo(uint8_t{thousand}); instead of a static_cast. With that, you would get a compiler error/warning if thousand is too large for uint8_t. But I don't know what lint thinks about it
This is a problem I also encountered. What I found to work best is to write a function which performs the cast for you and would generate an error in case something is wrong based on type traits.
#include <type_traits>
#include <limits>
template<class TYPE>
TYPE safe_cast(const Numbers& number)
{
using FROM_TYPE = std::underlying_type_t<Numbers>;
// Might have to add some additional code here to fix signed unsigned comparisons.
if((abs(std::numeric_limits<TYPE>::min()) > static_cast<FROM_TYPE>(number)) ||
(std::numeric_limits<TYPE>::max() < static_cast<FROM_TYPE>(number)))
{
// Throw an error or assert.
std::cout << "Error in safe_cast" << std::endl;
}
return static_cast<TYPE>(number);
}
Hope this wil help
p.s. In case you could rewrite this to compile time with a constexpr you could also uses static_assert.

Why can't I pass a constexpr function to std::cout? [duplicate]

This question already has answers here:
When does a constexpr function get evaluated at compile time?
(2 answers)
Closed 2 years ago.
This code, when compiled with g++ -O3, does not seem to evaluate get_fibonacci(50) at compile time - as it runs for a very long time.
#include <iostream>
constexpr long long get_fibonacci(int num){
if(num == 1 || num == 2){return 1;}
return get_fibonacci(num - 1) + get_fibonacci(num - 2);
}
int main()
{
std::cout << get_fibonacci(50) << std::endl;
}
Replacing the code with
#include <iostream>
constexpr long long get_fibonacci(int num){
if(num == 1 || num == 2){return 1;}
return get_fibonacci(num - 1) + get_fibonacci(num - 2);
}
int main()
{
long long num = get_fibonacci(50);
std::cout << num << std::endl;
}
worked perfectly fine. I don't know exactly why this is occurring, but my guess is that get_fibonacci(50) is not evaluated at compile-time in the first scenario because items given std::cout are evaluated at runtime. Is my reasoning correct, or is something else happening? Can somebody please point me in the right direction?
Actually, both versions of your code do not have the Fibonnaci number computed at compile-time, with typical compilers and compilation flags. But, interestingly enough, if you reduce the 50 to be, say, 30, both versions of your program do have the compile-time evaluation.
Proof: GodBolt
At the link, your first program is compiled and run first with 50 as the argument to get_fibbonacci(), then with 30, using GCC 10.2 and clang 11.0.
What you're seeing is the limits of the compiler's willingness to evaluate code at compile-time. Both compilers engage in the recursive evaluation at compile time - until a certain depth, or certain evaluation time cap, has elapsed. They then give up and leave it for run-time evaluation.
I don't know exactly why this is occurring, but my guess is that get_fibonacci(50) is not evaluated at compile-time in the first scenario because items given std::cout are evaluated at runtime
Your function can be computed compile-time, because receive a compile-time know value (50), but can also computed run-time, because the returned value is send to standard output so it's used run-time.
It's a gray area where the compiler can choose both solutions.
To impose (ignoring the as-if rule) the compile-time computation, you can place the returned value in a place where the value is required compile-time.
For example, in a template parameter, in your first example
std::cout << std::integral_constant<long long, get_fibonacci(50)>::value
<< std::endl;
or in a constexpr variable, in your second example
constexpr long long num = get_fibonacci(50);
But remember there is the "as-if rule", so the compiler (in this case, also using constexpr or std::integral_constant) can select the run-time solution because this "do not change the observable behavior of the program".
Assign to a constexpr to get the compiler to spit out an error message
constexpr auto val = get_fibonacci(50);
constexpr functions are evaluated at compile time only in constexpr context, which includes assignment to constexpr variables, template parameter, array size...
Regular function/operator call is not such context.
std::cout << get_fibonacci(50);
is done at runtime.
Now, compiler might optimize any (constexpr or not, inline or not) functions with the as-if rule, resulting in a constant, a simpler loop, ...

What should happen when this code is executed with input variables 0,1,2 and 3?

My question pertains to the following code, it is a classic textbook example:
#include <iostream>
#include <limits>
int main()
{
int min{std::numeric_limits<int>::max()}; ///These two limits
int max{std::numeric_limits<int>::min()};
bool any(false);
int x;
while (std::cin >> x)
{
any=true;
if (x<min)
min = x;
if (x)
max=x;
}
if (any)
std::cout << "min = " << "\nmax = " max << '\n';
}
Also, I was curious to know how to access the documentation that relates to the two limits i refer to in my comment above. Is this something that would be included in the C standard library?
Or would it be found in the documentation for the input / output streams library? In the limits library on cplusplus.com, the devs mention that the min=0, how is the max defined though? as in what are the parameters that define the max value and int could have in any C++ program?
http://en.cppreference.com/w/cpp/types/numeric_limits
http://www.cplusplus.com/reference/limits/numeric_limits/
These two links lead you to documentation about numerical limits in the C++ standard library.
"min()" is not "zero", it's the lowest possible value depending on the type you're using. For an int, the value is the lowest negative number, INT_MIN (probably –2147483648), not zero. For unsigned types, however, it's zero.
For some types, it might mean that all bits are set to 0, giving you the lowest possible value. For other types, it is not that simple.
"max()" is the highest possible value that the type can store. For some datatypes, it simply means that all bits are set to 1, giving you the highest possible value. For other types, it is not that simple, but the result is always the highest possible value that the type can store/represent, nonetheless.
For int, the highest possible value is INT_MAX, which is most likely 2147483647.
Going through your code and explaining exactly what happens, step by step, for the different input values feels out of scope, here, and sounds like I'm doing homework for you. You should try the code and see what happens.

Assigning 64-bit values under -pedantic-errors

I recently tried to solve Project Euler problem 3 using codepad.org and I noticed something strange.
As codepad used the flag -pedantic-errors, I couldn't use long long to store my number, but I noticed that I still could use uint64_t.
Here begins my problem.
Whereas I could define a variable as uint64_t, I had no good way of actually assigning the value.
I could assign the value in ugly ways (avert your eyes):
// This is very ugly code:
uint64_t s = 600851;
s *= 1000000;
s += 475143;
cout << "s = " << s << endl;
but I could not do a straight assignment like so:
// This gives me errors:
uint64_t s = 600851475143ULL;
Probably as it first interprets the right side as a long long.
So how is assignment actually supposed to work in this case?
Is it just a loophole that I can access the type, but not assign anything?
Are there any good workarounds if that's the case?

Type casting struct to integer and vice versa in C++

So, I've seen this thread Type casting struct to integer c++ about how to cast between integers and structs (bitfields) and undoubtly, writing a proper conversion function or overloading the relevant casting operators is the way to go for any cases where there is an operating system involved.
However, when writing firmware for a small embedded system where only one flash image is run, the case might be different insofar, as security isn't so much of a concern while performance is.
Since I can test whether the code works properly (meaning the bits of a bitfield are arranged the way I would expect them to be) each time when compiling my code, the answer might be different here.
So, my question is, whether there is a 'proper' way to convert between bitfield and unsigned int that does compile to no operations in g++ (maybe shifts will get optimised away when the compiler knows the bits are arranged correctly in memory).
This is an excerpt from the original question:
struct {
int part1 : 10;
int part2 : 6;
int part3 : 16;
} word;
I can then set part2 to be equal to whatever value is requested, and set the other parts as 0.
word.part1 = 0;
word.part2 = 9;
word.part3 = 0;
I now want to take that struct, and convert it into a single 32 bit integer. I do have it compiling by forcing the casting, but it does not seem like a very elegant or secure way of converting the data.
int x = *reinterpret_cast<int*>(&word);
EDIT:
Now, quite some time later, I have learned some things:
1) Type punning (changing the interpretation of data) by means of pointer casting is, undefined behaviour since C99 and C++98. These language changes introduced strict aliasing rules (They allow the compiler to reason that data is only accessed through pointers of compatible type) to allow for better optimisations. In effect, the compiler will not need to keep the ordering between accesses (or do the off-type access at all). For most cases, this does not seem to present a [immediate] problem, but when using higher optimisation settings (for gcc that is -O which includes -fstrict-aliasing) this will become a problem.
For examples see https://blog.regehr.org/archives/959
2) Using unions for type punning also seems to involve undefined behaviour in C++ but not C (See https://stackoverflow.com/a/25672839/4360539), however GCC (and probably others) does explicitly allow it: (See https://gcc.gnu.org/bugs/#nonbugs).
3) The only really reliable way of doing type punning in C++ seems to be using memcpy to copy the data to a new location and perform whatever is to be done and then to use another memcpy to return the changes. I did read somewhere on SO, that GCC (or most compilers probably) should be able to optimise the memcpy to a mere register copy for register-sized data types, but I cannot find it again.
So probably the best thing to do here is to use the union if you can be sure the code is compiled by a compiler supporting type punning through a union. For the other cases, further investigation would be needed how the compiler treats bigger data structures and memcpy and if this really involves copying back and forth, probably sticking with bitwise operations is the best idea.
union {
struct {
int part1: 10;
int part2: 6;
int part3: 16;
} parts;
int whole;
} word;
Then just use word.whole.
I had the same problem. I am guessing this is not very relevant today. But this is how I solved it:
#include <iostream>
struct PACKED{
int x:10;
int y:10;
int z:12;
PACKED operator=(int num )
{
*( int* )this = num;
return *this;
}
operator int()
{
int *x;
x = (int*)this;
return *x;
}
} __attribute__((packed));
int main(void) {
std::cout << "size: " << sizeof(PACKED) << std::endl;
PACKED bf;
bf = 0xFFF00000;
std::cout << "Values ( x, y, z ) = " << bf.x << " " << bf.y << " " << bf.z << std::endl;
int testint;
testint = bf;
std::cout << "As integer: " << testint << std::endl;
return 0;
}
This now fits on a int, and is assignable by standard ints. However I do not know how portable this solution is. The output of this is then:
size: 4
Values ( x, y, z ) = 0 0 -1
As integer: -1048576