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);
Related
I believe that when you add two unsigned int values together, the returned value's data type will be an unsigned int.
But the addition of two unsigned int values may return a value that is larger than an unsigned int.
So why does unsigned int + unsigned int return an unsigned int and not some other larger data type?
This would have truly evil consequences:
Would you really want 1 + 1 to be a long type? And (1 + 1) + (1 + 1) would become a long long type? It would wreak havoc with the type system.
It's also possible, for example, that short, int, long, and long long are all the same size, and similarly for the unsigned versions.
So the implicit type conversion rules as they stand are probably the best solution.
You could always force the issue with something like
0UL + "unsigned int" + "unsigned int"
Let's imagine that we have a language where adding two integers results in a bigger type. So, adding two 32 bit numbers results in a 64 bit number. What would happen in expression the following expression?
auto x = a + b + c + d + e + f + g;
a + b is 64 bits. a + b + c is 128 bits. a + b + c + d is 256 bits... This becomes unmanageable very fast. Most processors don't support operations with so wide operands.
The type of a varaible does not only determine the range of values it can hold, but sloppy speaking, also how the operations are realized. If you add two unsigned values you get an unsigned result. If you want a different type as result (eg long unsigned) you could cast:
unsigned x = 42;
unsigned y = 42;
long unsigned z = static_cast<long unsigned>(x) + static_cast<long unsigned>(y);
Actually the real reason is: It is defined like that. In particular unsigned overflow is well defined in C++ to wrap around and using a wider type for the result of unsigned operators would break that behaviour.
As a contrived example, consider this loop:
for (unsigned i = i0; i != 0; ++i) {}
Note the condition! Lets assume i0 > 0, then it can only ever be false when incrementing the maximum value of unsigned results in 0. This code is obfuscated and should probably make you raise an eyebrow or two in a code-review, though it is perfectly legal. Making the result type adjust depending on the value of the result, or choosing the result type such that overflow cannot happen would break this behaviour.
Because a variable + a same type variable can be only equal to that type variable ,
(well in some cases it will but not in your case)
example:
int + int = int a int plus another int cannot be equal to a float because it dont have the properties of a float.
I hope this answers your question bye!
I am trying to convert an unsigned long long to unsigned long. Is the following a correct way to do it?
unsigned long removeExtraBits2(unsigned long long c) {
return (unsigned long) ((c << 32) >> 32);
}
If not, can you provide a working example?
My assumption is that when shifting left, and then back right, the 32 leftmost bits get set to 0.
Thanks!
EDIT: The purpose of the conversion is to get rid of the extra bits, 'higher' than the 32nd, effectively keeping only the rightmost 32 bits into an unsigned long.
Just do a "plain" cast ((unsigned long)c, or, if you like verbosity, static_cast<unsigned long>(c), or even just assign the unsigned long long source value to the unsigned long target variable), the standard guarantees that the extra bits on the left will get truncated.
If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type).
(C++11, §4.7 ¶2)
which, if the source is unsigned (or is signed and in 2's complement arithmetic), is a fancy way to say that the extra bits are truncated.
There are many different processors and operating systems. The unsigned long long is 64-bits almost on everything. The unsigned long is the other story. It is for example 64-bits on Linux x86-64, 32-bits on Linux x86-32 and 32-bits on Windows x86-64 and x86-32. Plain convert may be noop.
I think this is a safe solution.
unsigned long removeExtraBits(unsigned long long c) {
c %= 0x100000000ULL;
return (unsigned long)(c);
}
Compiler will change % to simple mov.
There's no real need for a solution to this, I just want to know why.
Let's take two numbers:
#include <iostream>
using namespace std;
int main()
{
unsigned long long int a = 17446744073709551615;
signed long long int b = -30000000003;
signed int c;
c = a/b;
cout << "\n\n\n" << c << endl;
}
Now, lately the answer I've been getting is zero. The size of my long long is 8 bytes, so more than enough to take it with the unsigned label. The C variable should also be big enough to handle the answer. (It should be -581 558 136, according to Google). So...
Edit I'd like to point out that on my machine...
Using numeric_limits a falls well withing the maximum of 18446744073709551615 and b falls within the minimum limits of -9223372036854775808.
You have a number of implicit conversions happening, most of them unnecessary.
unsigned long long int a = 17446744073709551615;
An unsuffixed decimal integer literal is of type int, long int, or long long int; it's never of an unsigned type. That particular value almost certainly exceeds the maximum value of a long long int (263-1). Unless your compiler has a signed integer type wider than 64 bits, that makes your program ill-formed.
Add a ULL suffix to ensure that the literal is of the correct type:
unsigned long long int a = 17446744073709551615ULL;
The value happens to be between 263-1 and 264-1, so it fits in a 64-bit unsigned type but not in a 64-bit signed type.
(Actually just the U would suffice, but it doesn't hurt to be explicit.)
signed long long int b = -30000000003;
This shouldn't be a problem. 30000000003 is of some signed integer type; if your compiler supports long long, which is at least 64 bits wide, there's no overflow. Still, as long as you need a suffix on the value of a, it wouldn't hurt to be explicit:
signed long long int b = -30000000003LL;
Now we have:
signed int c;
c = a/b;
Dividing an unsigned long long by a signed long long causes the signed operand to be converted to unsigned long long. In this case, the value being converted is negative, so it's converted to a large positive value. Converting -30000000003 to unsigned long long yields 18446744043709551613. Dividing 17446744073709551615 by 18446744043709551613 yields zero.
Unless your compiler supports integers wider than 64 bits (most don't), you won't be able to directly divide 17446744073709551615 by -30000000003 and get a mathematically correct answer, since there's no integer type that can represent both values. All arithmetic operators (other than the shift operators) require operands of the same type, with implicit conversions applied as necessary.
In this particular case, you can divide 17446744073709551615ULL by 30000000003ULL and then account for the sign. (Check the language rules for division of negative integers.)
If you really need to do this in general, you can resort to floating-point (which means you'll probably lose some precision) or use some arbitrary width integer arithmetic package like GMP.
b is getting treated as an unsigned number which is larger than a. Hence you are getting the answer as 0.
Try using it as
c = abs(a) / abs (b)
if ((a < 0 && b > 0 ) || (a> 0 && b < 0))
return -c;
return c;
What I have is this
struct Record
{
unsigned char cat;
unsigned char len[2]={0x00, 0x1b}; // can't put short here because that
// whould change the size of the struct
unsigned char dat[253];
};
Record record;
unsigned short recordlen = *((unsigned short*)record.len);
This result in recordlen=0x1b00 instead of 0x001b
Same with *reinterpret_cast<unsigned short*>(record.len)
Can you explain why ? How should I be doing this ?
What you encounter is called "endianness". In x86, all numeric variables are stored "little endian", meaning the least-significant byte comes first.
From the Wikipedia page:
The little-endian system has the property that the same value can be read from memory at different lengths without using different addresses.
This depends on endianess of your cpu. See wikipedia.
In your case you have "little endian", which means that least significant bytes come first. This is convenient when you want to convert numbers to different byte sizes: if you use a long int to represent a short number, its representation is the same as if it were a short number, only it has additional zeroes at the end.
Can you explain why?
Because you cannot assume a specific endianness of your computer architecture.
The natural follow-up question is what do you do about it. Fortunately, you can force a specific byte order by calling one of these functions htonl, htons, ntohl, or ntohs. They work regardless of the computer architecture on which you run them:
On the sending end, you convert from host order to network order; on the receiving end, you convert from network order to host order.
// Sending end
unsigned short recordlen = calculate_len();
*reinterpret_cast<unsigned short*>(record.len) = htons(recordlen);
// Receiving end
unsigned short recordlen = ntohs(*reinterpret_cast<unsigned short*>(record.len));
unsigned short recordlen = *((unsigned short*)record.len);
This is broken. record.len doesn't point to an unsigned short. Telling the compiler it does is just lying.
I presume you want:
unsigned short recordlen = static_cast<unsigned short>(record.len[0]) * 256 +
static_cast<unsigned short>(record.len[1]);
Or, if you like it better:
unsigned short recordlen = (static_cast<unsigned short>(record.len[0]) << 8) |
static_cast<unsigned short>(record.len[1]);
If not, code whatever it is you actually want.
How to convert from long long to int and the other way back in c++ ??
also what are the properties of long long , especially its maximum size,
thank in advance ..
int is guaranteed to be at least 16 bits wide. On modern systems, it's most commonly 32 bits (even on 64-bit systems).
long long, which didn't originally exist in C++, is guaranteed to be at least 64 bits wide. It's almost always exactly 64 bits wide.
The usual way to convert a value from one integer type to another is simply to assign it. Any necessary conversion will be done implicitly. For example:
int x = 42;
long long y = 9223372036854775807;
y = x; // implicitly converts from int to long long
x = y; // implicitly converts from long long to int
For a narrowing conversion, where the target type can't represent all the values of the source type, there's a risk of overflow; int may or may not be able to hold the value 9223372036854775807. In this case, the result is implementation-defined. The most likely behavior is that the high-order bits are discarded; for example, converting 9223372036854775807 to int might yield 2147483647. (This is clearer in hexadecimal; the values are 0x7fffffffffffffff and 0x7fffffff, respectively.)
If you need to convert explicitly, you can use a cast. A C-style cast uses the type name in parentheses:
(long long)x
Or you can use a C++-style static_cast:
static_cast<long long>(x)
which is somewhat safer than a C-style cast because it's restricted in which types it can operate on.
Type long long is typically 64 bits.
Type int is likely to be 32 bits, but not on all machines.
If you cast an int to a long long, you can do
my_long_long = (long long) my_int
and it will be just fine. If you go the other direction, like
my_int = (int) my_long_long
and the int is smaller than 64-bits, it won't be able to hold all the information, so the result may not be correct.
Size of int is only 2 bytes whereas the other one is usually larger than int. So if you are looking to convert long into int then you would end up loosing information. But the other way is possible without sacrificing the correctness of information.
Suppose a is of long type and b is of int type. Then int to long covertion:a=(long)b; . For other way:b=(int)a;.