In the code base, I often see people writing
void f(unsigned int){/* some stuff*/ }; // define f here
f(0) // call f later
unsigned int a = 0;
double d = 0;
Initialized number (0 here) not matching the declared type annoys me, if this is performance critical code, does this kind of initialization hurt performance?
EDIT
For the downvoters:
I did search before I posted the question, c++ is famous for hidden rules, i didn't know integer promotion rules until someone commented under this question. For people saying "even stupid compiler won't do conversion at run time", here below is an example from this answer
float f1(float x) { return x*3.14; }
float f2(float x) { return x*3.14F; }
These two versions have different performance, and to an unexperienced c++ programmer, I don't see much difference between my question and this example. And C++ is famous for hidden rules and pitfalls, which means intuition sometimes is not right, so why it is getting downvoted to ask a question like this?
You are right that 0 is an int, not a double (0. would be) nor an unsigned int. This does not matter here though as int is implicitly convertible to those types and 0 can be represented perfectly by both of them. There's no performance implication either; the compiler does it all at compile time.
if this is performance critical code, does this kind of initialization hurt performance?
Very unlikely so. Even without any optimization enabled there is no reason for a compiler to generate code to get original value and convert to type of variable instead of initializing by converted representation of that type (if that conversion is necessary). Though this may affect your code if you use new style, that some people recommend to use in modern C++
auto a = 0U; // if you do not specify U then variable type would be signed int
to use this style or not is a subjective question.
For your addition:
float f1(float x) { return x*3.14; }
float f2(float x) { return x*3.14F; }
this case is quite different. In the first case x is promoted to double calculations with double is used and then result is converted to float, while on the second case float is multiplied by float. Difference is significant - you either convert compile time constant of one type to constant of another or use calculations with that types.
Related
I am trying to write a C++ code for conversion of assembly dq 3FA999999999999Ah into C++ double. What to type inside asm block? I dont know how to take out the value.
int main()
{
double x;
asm
{
dq 3FA999999999999Ah
mov x,?????
}
std::cout<<x<<std::endl;
return 0;
}
From the comments it sounds a lot like you want to use a reinterpret cast here. Essentially what this does is to tell the compiler to treat the sequence of bits as if it were of the type that it was casted to but it doesn't do any attempt to convert the value.
uint64_t raw = 0x3FA999999999999A;
double x = reinterpret_cast<double&>(raw);
See this in action here: http://coliru.stacked-crooked.com/a/37aec366eabf1da7
Note that I've used the specific 64bit integer type here to make sure the bit representation required matches that of the 64bit double. Also the cast has to be to double& because of the C++ rules forbidding the plain cast to double. This is because reinterpret cast deals with memory and not type conversions, for more details see this question: Why doesn't this reinterpret_cast compile?. Additionally you need to be sure that the representation of the 64 bit unsigned here will match up with the bit reinterpretation of the double for this to work properly.
EDIT: Something worth noting is that the compiler warns about this breaking strict aliasing rules. The quick summary is that more than one value refers to the same place in memory now and the compiler might not be able to tell which variables are changed if the change occurs via the other way it can be accessed. In general you don't want to ignore this, I'd highly recommend reading the following article on strict aliasing to get to know why this is an issue. So while the intent of the code might be a little less clear you might find a better solution is to use memcpy to avoid the aliasing problems:
#include <iostream>
int main()
{
double x;
const uint64_t raw = 0x3FA999999999999A;
std::memcpy(&x, &raw, sizeof raw);
std::cout<<x<<std::endl;
return 0;
}
See this in action here: http://coliru.stacked-crooked.com/a/5b738874e83e896a
This avoids the issue with the aliasing issue because x is now a double with the correct constituent bits but because of the memcpy usage it is not at the same memory location as the original 64 bit int that was used to represent the bit pattern needed to create it. Because memcpy is treating the variable as if it were an array of char you still need to make sure you get any endianness considerations correct.
Will use a constexpr instead of const better help compile to optmize? I have some value that are constant. I could use an enum instead of but they aren't all of same type and I don't want to use #defines for ovious reasons. They are declared like below code. My question is: if I use constexpr will it increase possibilities to compiler replace the value where it's used by the literal constant value or it doesn't differ if I use const? I know it's up to each compiler if does or doesn't the optmization but a "general" answer as it behave in most compiler is very welcome. Also, assuming the result are different for simple locals like this it's different too if instead of they are member of a struct/class? is const folding most hard to be performed in this cases?
e.g,
int foo()
{
constexpr int x = 10;
constexpr int y = x * 3;
do_domsething(y + n);
}
versus
int foo()
{
const int x = 10;
const int y = x * 3;
do_domsething(y + n);
}
Today, constexpr is still pretty new and might fall through some optimization cracks. Calculation of the variable's own value is required to be performed at compile time, of course. In the long run, I'd expect the same optimization opportunities for each. Obviously when that happens is compiler-specific.
Just use whichever one has clearer meaning to you and anyone else working on the code, not only in terms of behavior but also intent.
Among other things, note that constexpr guarantees the constant has the same value always, whereas const allows it to have a different value each time initialization is reached (it can't be changed except by initialization, of course). But nearly every compiler on the planet will determine that for your example, the values really are constant.
One more thing: constexpr compile-time evaluation (like template argument calculation) is active even when optimizations are disabled.
Casts are used for both type conversion and disambiguation. In further research I found these two as examples :
(double) 3; // conversion
(double) 3.0; // disambiguation
Can someone explain the difference, I don't see any. Is this distinction, also valid in C++
EDIT
Originally the code snippet was like so:
(float) 3; // conversion
(float) 3.0; // disambiguation
But changed it to double because floating point literals are no longer float in modern compilers and the question had no meaning. I hope I interpreted the comments correctly and I appologize for any answer already posted that became irrelevant after the edit.
The (double) 3 is a conversion from an Integer (int) to a floting point number (double).
The cast in (double) 3.0 is useless, it doesn't do anything since it's already double.
An unsuffixed floating constant has type double.
(ANSI C Standard, ยง3.1.3.1 Floating constants)
This answer is valid for C, it should be the same in C++.
This is similar to many things asked of programmers in any language. I will give a first example, which is different from what you are asking, but should illustrate better why this would appear wherever you've seen it.
Say I define a constant variable:
static const a = 5;
Now, what is 'a'? Let's try again...
static const max_number_of_buttons = 5;
This is explicit variable naming. It is much longer, and in the long run it is likely to save your ass. In C++ you have another potential problem in that regard: naming of member variables, versus local and parameter variables. All 3 should make use of a different scheme so when you read your C++ function you know exactly what it is doing. There is a small function which tells you nothing about the variables:
void func(char a)
{
char b;
b = a;
p = b * 3;
g = a - 7;
}
Using proper naming conventions and you would know whether p and g are local variables, parameters to the function, variable members, or global variables. (This function is very small so you have an idea, imagine a function of 1,000 lines of code [I've seen those], after a couple pages, you have no idea what's what and often you will shadow variables in ways that are really hard to debug...)
void func(char a)
{
char b;
b = a;
g_p = b * 3;
f_g = a - 7;
}
My personal convention is to add g_ for global variables and f_ for variable members. At this point I do not distinguish local and parameter variables... although you could write p_a instead of just a for the parameter and now you know for all the different types of variables.
Okay, so that makes sense in regard for disambiguation of variable names, although in your case you specifically are asking about types. Let's see...
Ada is known for its very strong typing of variables. For example:
type a is 1 .. 100;
type b is 1 .. 100;
A: a;
B: b;
A := 5;
B := A;
The last line does NOT compile. Even though type a and type b look alike, the compiler view them both as different numeric types. In other words, it is quite explicit. To make it work in Ada, you have to cast A as follow:
B := B'(A);
The same in C/C++, you declare two types and variables:
typedef int a;
typedef int b;
a A;
b B;
A = 5;
B = A;
That works as is in C/C++ because type a and type b are considered to be exactly the same (int, even though you gave them names a and b). It is dearly NOT explicit. So writing something like:
A = (b) 5;
would explicitly tell you that you view that 5 as of type b and convert it (implicitly) to type a in the assignment. You could also write it in this way to be fully explicit:
A = a(b(5));
Most C/C++ programmers will tell you that this is silly, which is why we have so many bugs in our software, unfortunately. Ada protects you against mixing carrots and bananas because even if both are defined as integers they both are different types.
Now there is a way to palliate to that problem in C/C++, albeit pretty much never used, you can make use of a class for each object, including numbers. Then you'd have a specific type for each different type (because variables of class A and class B cannot just be mixed together, at least not unless you allow it by adding functions for the purpose.) Very frankly, even I do not do that because it would be way too much work to write any C program of any length...
So as Juri said: 3.0 and (double) 3.0 are exactly the same thing and the (double) casting is redundant (a pleonasm, as in you say the same thing twice). Yet, it may help the guy who comes behind you see that you really meant for that number to be a double and not whatever the language says it could eventually be.
Given this starting point:
double y = readDoubleValue();
Is there any significant difference in C++ between:
int x = y;
and
int x = trunc(y);
Which one should I prefer? If somebody else (including my future self :) ) reads my code, it looks to me that with the second it's more explicit the fact that I know exactly what I am doing, however it requires a library inclusion.
Reference:
Is there a trunc function in C++?
Just using static_cast<int>(y) will give all the benefits you are looking for:
truncation
the casting
explicit conversion for clarity.
the reasons why I won't use trunc()
it is not that common, and probably someone else reading your code will have to review the documentation (that is why I did, but again, I'm not an expert)
you are still using implicit conversion anyway, trunc() doesn't return an int.
for me it is not explicit enough, after reading your code and the documentation I asked myself this: "did he intent casting to int, or you just wanted a float without the fraction part"
I can think of a situation or two where I want to get rid of the fraction part but I still want to the variable to have the type float for several reasons like, I want the operation x + 0.1f to save the fraction part.
so I still would have doubts about your intentions, maybe you didn't mean the implicit conversion.
OR you can just put a little comment next to it int x = y; // yes, I know what I'm doing.This will also give the clarity you need.
IMO you should not. The truncate is a function defined for floating point types. It does not change type into integral type.
int x = y; here you say you are assigning something to an int variable
int x = trunc(y); here you say you drop the fractional part part for whatever reason, then convert
Use-cases are pretty different in my opinion.
Why would I discourage use of trunc before conversion. Probably preference, to me its kind of obfuscation actually in such use-case.
The code below performs a fast inverse square root operation by some bit hacks.
The algorithm was probably developed by Silicon Graphics in early 1990's and it's appeared in Quake 3 too.
more info
However I get the following warning from GCC C++ compiler: dereferencing type-punned pointer will break strict-aliasing rules
Should I use static_cast, reinterpret_cast or dynamic_cast instead in such situations?
float InverseSquareRoot(float x)
{
float xhalf = 0.5f*x;
int32_t i = *(int32_t*)&x;
i = 0x5f3759df - (i>>1);
x = *(float*)&i;
x = x*(1.5f - xhalf*x*x);
return x;
}
Forget casts. Use memcpy.
float xhalf = 0.5f*x;
uint32_t i;
assert(sizeof(x) == sizeof(i));
std::memcpy(&i, &x, sizeof(i));
i = 0x5f375a86 - (i>>1);
std::memcpy(&x, &i, sizeof(i));
x = x*(1.5f - xhalf*x*x);
return x;
The original code tries to initialize the int32_t by first accessing the float object through an int32_t pointer, which is where the rules are broken. The C-style cast is equivalent to a reinterpret_cast, so changing it to reinterpret_cast would not make much difference.
The important difference when using memcpy is that the bytes are copied from the float into the int32_t, but the float object is never accessed through an int32_t lvalue, because memcpy takes pointers to void and its insides are "magical" and don't break the aliasing rules.
There are a few good answers here that address the type-punning issue.
I want to address the "fast inverse square-root" part. Don't use this "trick" on modern processors. Every mainstream vector ISA has a dedicated hardware instruction to give you a fast inverse square-root. Every one of them is both faster and more accurate than this oft-copied little hack.
These instructions are all available via intrinsics, so they are relatively easy to use. In SSE, you want to use rsqrtss (intrinsic: _mm_rsqrt_ss( )); in NEON you want to use vrsqrte (intrinsic: vrsqrte_f32( )); and in AltiVec you want to use frsqrte. Most GPU ISAs have similar instructions. These estimates can be refined using the same Newton iteration, and NEON even has the vrsqrts instruction to do part of the refinement in a single instruction without needing to load constants.
Update
I no longer believe this answer is correct, due to feedback I've gotten from the committee. But I want to leave it up for informational purposes. And I am purposefully hopeful that this answer can be made correct by the committee (if it chooses to do so). I.e. there's nothing about the underlying hardware that makes this answer incorrect, it is just the judgement of a committee that makes it so, or not so.
I'm adding an answer not to refute the accepted answer, but to augment it. I believe the accepted answer is both correct and efficient (and I've just upvoted it). However I wanted to demonstrate another technique that is just as correct and efficient:
float InverseSquareRoot(float x)
{
union
{
float as_float;
int32_t as_int;
};
float xhalf = 0.5f*x;
as_float = x;
as_int = 0x5f3759df - (as_int>>1);
as_float = as_float*(1.5f - xhalf*as_float*as_float);
return as_float;
}
Using clang++ with optimization at -O3, I compiled plasmacel's code, R. Martinho Fernandes code, and this code, and compared the assembly line by line. All three were identical. This is due to the compiler's choice to compile it like this. It had been equally valid for the compiler to produce different, broken code.
If you have access to C++20 or later then you can use std::bit_cast
float InverseSquareRoot(float x)
{
float xhalf = 0.5f*x;
int32_t i = std::bit_cast<int32_t>(x);
i = 0x5f3759df - (i>>1);
x = std::bit_cast<float>(i);
x = x*(1.5f - xhalf*x*x);
return x;
}
At the moment std::bit_cast is only supported by MSVC. See demo on Godbolt
While waiting for the implementation, if you're using Clang you can try __builtin_bit_cast. Just change the casts like this
int32_t i = __builtin_bit_cast(std::int32_t, x);
x = __builtin_bit_cast(float, i);
Demo
Take a look at this for more information on type punning and strict aliasing.
The only safe cast of a type into an array is into a char array. If you want one data address to be switchable to different types you will need to use a union
The cast invokes undefined behaviour. No matter what form of cast you use, it will still be undefined behaviour. It is undefined no matter what type of cast you use.
Most compilers will do what you expect, but gcc likes being mean and is probably going to assume you didn't assign the pointers despite all indication you did and reorder the operation so they give some strange result.
Casting a pointer to incompatible type and dereferencing it is an undefined behaviour. The only exception is casting it to or from char, so the only workaround is using std::memcpy (as per R. Martinho Fernandes' answer). (I am not sure how much it is defined using unions; It does stand a better chance of working though).
That said, you should not use C-style cast in C++. In this case, static_cast would not compile, nor would dynamic_cast, forcing you to use reinterpret_cast and reinterpret_cast is a strong suggestion you might be violating strict aliasing rules.
Based on the answers here I made a modern "pseudo-cast" function for ease of application.
C99 version
(while most compilers support it, theoretically could be undefined behavior in some)
template <typename T, typename U>
inline T pseudo_cast(const U &x)
{
static_assert(std::is_trivially_copyable<T>::value && std::is_trivially_copyable<U>::value, "pseudo_cast can't handle types which are not trivially copyable");
union { U from; T to; } __x = {x};
return __x.to;
}
Universal versions
(based on the accepted answer)
Cast types with the same size:
#include <cstring>
template <typename T, typename U>
inline T pseudo_cast(const U &x)
{
static_assert(std::is_trivially_copyable<T>::value && std::is_trivially_copyable<U>::value, "pseudo_cast can't handle types which are not trivially copyable");
static_assert(sizeof(T) == sizeof(U), "pseudo_cast can't handle types with different size");
T to;
std::memcpy(&to, &x, sizeof(T));
return to;
}
Cast types with any sizes:
#include <cstring>
template <typename T, typename U>
inline T pseudo_cast(const U &x)
{
static_assert(std::is_trivially_copyable<T>::value && std::is_trivially_copyable<U>::value, "pseudo_cast can't handle types which are not trivially copyable");
T to = T(0);
std::memcpy(&to, &x, (sizeof(T) < sizeof(U)) ? sizeof(T) : sizeof(U));
return to;
}
Use it like:
float f = 3.14f;
uint32_t u = pseudo_cast<uint32_t>(f);
Update for C++20
C++20 introduces constexpr std::bit_cast in header <bit> which is functionally equivalent for types with the same size. Nevertheless, the above versions are still useful if you want to implement this functionality yourself (supposed that constexpr is not required), or if you want to support types with different sizes.
The only cast that will work here is reinterpret_cast. (And
even then, at least one compiler will go out of its way to
ensure that it won't work.)
But what are you actually trying to do? There's certainly
a better solution, that doesn't involve type punning. There are
very, very few cases where type punning is appropriate, and they
all are in very, very low level code, things like serialization,
or implementing the C standard library (e.g. functions like
modf). Otherwise (and maybe even in serialization), functions
like ldexp and modf will probably work better, and certainly
be more readable.