could any please explain the below code
const uInt32 eVal = 8ul;
const uInt32 fVal = 5ul;
const uInt32 zVal = 0ul;
what does ul and numbers 8,5,0 are stand for
It's the programmer being unnecessarily verbose. ul is the prefix for an unsigned long literal, so 8ul has an unsigned long type.
Most likely, that isn't the same type as the uInt32, so really the code you present is an exercise in obfuscation. Really they should rely on the automatic implicit conversion rules and write
const uInt32 eVal = 8;
const uInt32 fVal = 5;
const uInt32 zVal = 0;
perhaps even preferring constexpr in place of const.
Reference: http://en.cppreference.com/w/cpp/language/implicit_conversion
ul stands for unsigned long representation of numbers. Here the number 8 or 5 or 0 of type unsigned long is being assigned to constant uInt32 type variable.
The 'ul' is used for representation. It need not be used also.
Related
A byte of data is being stored in a 'char' member variable. It should probably be stored as an 'unsigned char' instead, but that can't be changed. I need to retrieve it through an 'int' variable, but without propagating the sign bit.
My solution was this (UINT and UCHAR are the obvious types):
void Foo::get_data( int *val )
{
if( val )
*val = (int)(UINT)(UCHAR)m_data; // 'm_data' is type 'char'
}
This seemed the best solution to me. I could use
*val = 0xff & (int)m_data;
instead of the casting, but this doesn't seem as readable. Which alternative is better, if either, and why?
Just write
*val = (UCHAR)m_data;
As now the expression (UCHAR)m_data has an unsigned type neither sign bit will be propagated.
The type of conversion here is Integral promotion.
When promoting to a wider integer type the value is always "widened" using its signedness, so that the sign is propagated to the new high order bits for signed values. To avoid the sign propagation convert a signed value to its corresponding unsigned type first.
You can do that with an explicit *val = static_cast<UCHAR>(m_data).
Or, safer, using as_unsigned function as *val = as_unsigned(m_data). Function as_unsigned looks like:
inline unsigned char as_unsigned(char a) { return a; }
inline unsigned char as_unsigned(unsigned char a) { return a; }
inline unsigned char as_unsigned(signed char a) { return a; }
// And so on for the rest of integer types.
Using as_unsigned eliminates the risk of that explicit cast becoming incorrect after maintenance, should m_data become a wider integer it will use another overload of as_unsigned automatically without requiring the maintainer to manually update the expression. The inverse function as_signed is also useful.
The cast is better because some compilers (eg. clang) actually generate extra code for the bitwise and. Of course, you only need the one cast to unsigned char.
The cast also expresses your intent better: the data is actually an unsigned char that you move to an int. So I would call it better even with compilers which generate the same code.
I am going trough the book "Accelerated C++" by Andrew Koenig and Barbara E. Moo and I have some questions about the main example in chap 2. The code can be summarized as below, and is compiling without warning/error with g++:
#include <string>
using std::string;
int main()
{
const string greeting = "Hello, world!";
// OK
const int pad = 1;
// KO
// int pad = 1;
// OK
// unsigned int pad = 1;
const string::size_type cols = greeting.size() + 2 + pad * 2;
string::size_type c = 0;
if (c == 1 + pad)
{;}
return 0;
}
However, if I replace const int pad = 1; by int pad = 1;, the g++ compiler will return a warning:
warning: comparison between signed and unsigned integer expressions [-Werror=sign-compare]
if (c == 1 + pad)
If I replace const int pad = 1; by unsigned int pad = 1;, the g++ compiler will not return a warning.
I understand why g++ return the warning, but I am not sure about the three below points:
Is it safe to use an unsigned int in order to compare with a std::string::size_type? The compiler does not return a warning in that case but I am not sure if it is safe.
Why is the compiler not giving a warning with the original code const int pad = 1. Is the compiler automatically converting the variable pad to an unsigned int?
I could also replace const int pad = 1; by string::size_type pad = 1;, but the meaning of the variable pad is not really linked to a string size in my opinion. Still, would this be the best approach in that case to avoid having different types in the comparison?
From the compiler point of view:
It is unsafe to compare signed and unsinged variables (non-constants).
It is safe to compare 2 unsinged variables of different sizes.
It is safe to compare an unsigned variable with a singed constant if the compiler can check that constant to be in the allowed range for the type of the signed variable (e.g. for 16-bit signed integer it is safe to use a constant in range [0..32767]).
So the answers to your questions:
Yes, it is safe to compare unsigned int and std::string::size_type.
There is no warning because the compiler can perform the safety check (while compiling :)).
There is no problem to use different unsigned types in comparison. Use unsinged int.
Comparing signed and unsigned values is "dangerous" in the sense that you may not get what you expect when the signed value is negative (it may well behave as a very large unsigned value, and thus a > b gives true when a = -1 and b = 100. (The use of const int works because the compiler knows the value isn't changing and thus can say "well, this value is always 1, so it works fine here")
As long as the value you want to compare fits in unsigned int (on typical machines, a little over 4 billion) is fine.
If you are using std::string with the default allocator (which is likely), then size_type is actually size_t.
[support.types]/6 defines that size_t is
an implementation-defined unsigned integer type that is large enough to contain the size
in bytes of any object.
So it's not technically guaranteed to be a unsigned int, but I believe it is defined this way in most cases.
Now regarding your second question: if you use const int something = 2, the compiler sees that this integer is a) never negative and b) never changes, so it's always safe to compare this variable with size_t. In some cases the compiler may optimize the variable out completely and simply replace all it's occurrences with 2.
I would say that it is better to use size_type everywhere where you are to the size of something, since it is more verbose.
What the compiler warns about is the comparison of unsigned and signed integer types. This is because the signed integer can be negative and the meaning is counter intuitive. This is because the signed is converted to unsigned before comparison, which means the negative number will compare greater than the positive.
Is it safe to use an unsigned int in order to compare with a std::string::size_type? The compiler does not return a warning in that case but I am not sure if it is safe.
Yes, they are both unsigned and then the semantics is what's expected. If their range differs the narrower are converted to a wider type.
Why is the compiler not giving a warning with the original code const int pad = 1. Is the compiler automatically converting the variable pad to an unsigned int?
This is because how the compiler is constructed. The compiler parses and to some extent optimizes the code before warnings are issued. The important point is that at the point this warning is being considered the compiler nows that the signed integer is 1 and then it's safe to compare with a unsigned integer.
I could also replace const int pad = 1; by string::size_type pad = 1;, but the meaning of the variable pad is not really linked to a string size in my opinion. Still, would this be the best approach in that case to avoid having different types in the comparison?
If you don't want it to be constant the best solution would probably be to make it at least an unsigned integer type. However you should be aware that there is no guaranteed relation between normal integer types and sizes, for example unsigned int may be narrower, wider or equal to size_t and size_type (the latter may also differ).
I have variable of type int *alen. Trying to pass it to function:
typedef int(__stdcall *Tfnc)(
unsigned int *alen
);
with casting
(*Tfnc)( (unsigned int *)alen )
Can I expect problems in case value is never negative?
Under the C++ standard, what you are doing is undefined behavior. The memory layout of unsigned and signed ints is not guaranteed to be compatible, as far as I know.
On most platforms (which use 2s complement integers), this will not be a problem.
The remaining issue is strict aliasing, where the compiler is free to presume that pointers to one type and pointers to another type are not pointers to the same thing.
typedef int(__stdcall *Tfnc)(
unsigned int *alen
);
int test() {
int x = 3;
Tfnc pf = [](unsigned int* bob) { *bob = 2; };
pf((unsigned int*)&x);
return x;
}
the above code might be allowed to ignore the modification to the x while it is modified through the unsigned int*, even on 2s complement hardware.
That is the price of undefined behavior.
No it won't be of any problem, until and unless the int value you pass is not negative.
But if the given value is negative then the resulting value is the least unsigned integer congruent to the source integer (modulo 2^n where n is the number of bits used to represent the unsigned type).
(In C/C++)
//1
int i = 1;
unsigned u = i;
//2
int i = 1;
unsigned u = (unsigned)i;
//3
unsigned u = 1;
//4
unsigned u = 1u;
The gcc (4.8) compiler makes no difference in the assembly code produced between 1, 2 and 3, 4 each. When writing actual code, (to me) it is often more convenient to use the form 1 and 3 unless it is outside the range of the positive signed. (such as 3,333,333,333 for 32 bit int)
With this function,
void mpz_set_ui (mpz_t rop, unsigned long int op)
I use it as,
mpz_set_ui(num, 3); //or an int variable in place of 3
, for example.
My understanding of the current C(++) standard is that it is unnecessary to explicitly state as unsigned in the above cases, but I am not sure whether in some cases there may be some additional tasks to convert from signed to unsigned, or is it always the exactly same executable when the substituted signed variable is within the range of the target unsigned variable.
There will be no actual difference in the conversion result, the implicit and explicit conversion do the same thing. The advantage of the explicit cast, preferable static_cast in C++, is clarity: If you write the explicit cast, no one needs to wonder if you changed signedness on accident. I would consider 3) and 4) equally good.
How could one "split" i.e. long long type, so that first part of it is in var of type long and second part is also in var of type long.
long long long_type = 0xaaaabbbbccccdddd;
and in first int I would like to have first half(doesn't matter from what side) of the long_type var and in second var int second half.
Your question is ambiguous. It depends on what you mean by "split". You can split the value representation of your original long long or you can split the object representation of your long long.
If you want to split the value representation, then your question is even more ambiguous due to the fact that your original value is signed. How do you intend to split a signed value? What kind of result do you expect? Signed? Unsigned? High-order part signed, low-order part unsigned? Or something else?
For an unsigned value it would look as follows (assuming that the recipient type long has the right size for your purposes)
unsigned long long long_type = ...;
unsigned long hi = long_type / ULONG_MAX;
unsigned long lo = long_type;
If you want to split the object representation, the proper way to do it would be to use memcpy (in this case the signedness of the original value is not of importance)
long long long_type = ...;
unsigned long hi, lo;
memcpy(&lo, &long_type, sizeof lo);
memcpy(&hi, (char *) &long_type + sizeof lo, sizeof hi);
In this case, of course, which part is actually the low-order one and which part is the high-order one will depend on the platform.
I'd recommend using uint32_t and uint64_t or other fixed width types.
Then use bit operations to split it like:
uint64_t long_type = smthng;
uint32_t high = (long_type & 0xFFFFFFFF00000000ULL) >> 32;
uint32_t low = long_type & 0xFFFFFFFF;
long a = long_type;
long b = (static_cast<unsigned long long>(long_type) >> 32);