Representation of Long Integers [duplicate] - c++

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
What is the difference between an int and a long in C++?
#include <iostream>
int main()
{
std::cout << sizeof(int) << std::endl;
std::cout << sizeof(long int) << std::endl;
}
Output:
4
4
How is this possible? Shouldn't long int be bigger in size than int?

The guarantees you have are:
sizeof(int) <= sizeof(long)
sizeof(int) * CHAR_BITS >= 16
sizeof(long) * CHAR_BITS >= 32
CHAR_BITS >= 8
All these conditions are met with:
sizeof(int) == 4
sizeof(long) == 4

C++ langauge never guaranteed or required long int to be bigger than int. The only thing the language is promising is that long int is not smaller than int. In many popular implementations long int has the same size as int.

It depends on the language and the platform. In ISO/ANSI C, For example, the long integer type is 8 bytes in 64-bit system Unix, and 4 bytes in other os/platforms.

No. It's valid under the C standard for int to be the same size as short int, for int to be the same size as long int, for int not to be the same as either long int or short int, or even for all three to be the same size. On 16-bit machines it was common for sizeof(int) == sizeof(short int) == 2 and sizeof(long int) == 4, but the most common arrangement on 32-bit machines is sizeof(int) == sizeof(long int) == 4 and sizeof(short int) == 2. And on 64-bit machines you may find sizeof(short int) == 2, sizeof(int) == 4, and sizeof(long int) == 8.

See http://bytes.com/topic/c/answers/163333-sizeof-int-sizeof-long-int.
No nothing is wrong. The size of data-types is generally hardware dependant (exception being char which is always 1 register wide). In gcc/Unix, int and long int both require 4 bytes. You can also try sizeof(long long int) and see the results and sizeof(short int).

Related

Why doesn't a negative number modulo a vector size give a negative number? [duplicate]

This question already has an answer here:
C++ size_t modulus operation with negative operand
(1 answer)
Closed 2 years ago.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<int> v = {1, 2, 3, 4, 5, 6, 7};
int i = -4;
cout << i << endl;
cout << v.size() << endl;
cout << i % v.size() << endl;
cout << -4 % 7 << endl;
}
The above code prints:
-4
7
5
-4
Can someone please explain why i % v.size() prints 5 instead of -4? I'm guessing it has something to do with vector.size(), but unsure what the underlying reasoning is. Thanks in advance.
The operands of % undergo the usual arithmetic conversions to bring them to a common type, before the division is performed. If the operands were int and size_t, then the int is converted to size_t.
If size_t is 32-bit then -4 would become 4294967292 and then the result of the expression is 4294957292 % 7 which is actually 0.
If size_t is 64-bit then -4 would become 18,446,744,073,709,551,612 and the result of this % 7 is 5 which you saw.
So actually we can tell from this output that your system has 64-bit size_t.
In C++ the modulus operator is defined so that the following is true for all integers except for b == 0:
(a/b)*b + a%b == a
So it is forced to be consistent with the integer division, which from C++ 11 onwards truncates to zero even for negative numbers. Hence everything is well defined even for negative numbers.
However, in your case you have an signed / unsigned division (because .size() returns unsigned) and the usual signed/unsigned rules apply. This means that in this case all arguments are converted to unsigned before the operation is carried out (see also Ruslan's comment).
So -4 is converted to unsigned (and becomes a very large number) and then modulo is carried out.
You can also see this as 5 is not a correct answer for -4 modulo 7 with any definition of integer division (3 would be correct).
Arithmetic rules with C and C++ are not intuitive.
Because v.size return size_t.
cout << -4 % size_t(7) << endl; // 5
Take a look modulo-operator-with-negative-values
UPD: and signed-int-modulo-unsigned-int-produces-nonsense-results
This is due to the type of v.size(), which is an unsigned type. Due to integer promotion, this means that the result will also be treated as unsigned, despite i being a signed type.
I am assuming you are compiling on 64 bit. This means that in addition to promotion to unsigned, the result will also be of the 64 bit type unsigned long long. Step by step:
unsigned long long _i = (unsigned long long)-4; // 0xFFFFFFFFFFFFFFFC!
unsigned long long result = _i % (unsigned long long)7; // 5
Since presumably you want to preserve the signedness of i, in this case it is enough to cast v.size() to a signed type to prevent the promotion to unsigned:
i % (int)v.size() will give -4.
From cppreference on Usual arithmetic conversions and C++ standard
Otherwise (the signedness is different): If the unsigned type has conversion rank greater than or equal to the rank of the signed type, then the operand with the signed type is implicitly converted to the unsigned type.
-4 is signed and 7 is size_t which is an unsigned type, so -4 is converted to unsigned first and then modulus is carried out.
With that mind, if you break it down, you will immediately see what is happening:
size_t s = -4; // s = 18446744073709551612 on a 64 bit system
size_t m = 7;
std::cout << s % m << '\n'; //5
The results might be different for a 32-bit system.
cout << -4 % 7 << endl; still prints -4. Why? It's because the type of both -4 and 7 is int.
C++ standard ยง5.13.2.3 Type of an integer literal
The type of an integer-literal is the first type in the list in Table 8 corresponding to its optional integer-suffix in which its value can be represented. An integer-literal is a prvalue.
Table 8: Types of integer-literals without suffix:
int
long int
long long int
So, -4 and 7 both are int in this case and hence the result of modulo is -4.

Make a Integer from 6 bytes or more using C++

I am new in C++ programming. I am trying to implement a code through which I can make a single integer value from 6 or more individual bytes.
I have Implemented same for 4 bytes and it's working
My Code for 4 bytes:
char *command = "\x42\xa0\x82\xa1\x21\x22";
__int64 value;
value = (__int64)(((unsigned char)command[2] << 24) + ((unsigned char)command[3] << 16) + ((unsigned char)command[4] << 8) + (unsigned char)command[5]);
printf("%x %x %x %x %x",command[2], command[3], command[4], command[5], value);
Using this Code the value of value is 82a12122 but when I try to do for 6 byte then the result was is wrong.
Code for 6 Bytes:
char *command = "\x42\xa0\x82\xa1\x21\x22";
__int64 value;
value = (__int64)(((unsigned char)command[0] << 40) + ((unsigned char)command[1] << 32) + ((unsigned char)command[2] << 24) + ((unsigned char)command[3] << 16) + ((unsigned char)command[4] << 8) + (unsigned char)command[5]);
printf("%x %x %x %x %x %x %x", command[0], command[1], command[2], command[3], command[4], command[5], value);
The output value of value is 82a163c2 which is wrong, I need 42a082a12122.
So can anyone tell me how to get the expected output and what is wrong with the 6 Byte Code.
Thanks in Advance.
Just cast each byte to a sufficiently large unsigned type before shifting. Even after integral promotions (to unsigned int), the type is not large enough to shift by more than 32 bytes (in the usual case, which seems to apply to you).
See here for demonstration: https://godbolt.org/g/x855XH
unsigned long long large_ok(char x)
{
return ((unsigned long long)x) << 63;
}
unsigned long long large_incorrect(char x)
{
return ((unsigned long long)x) << 64;
}
unsigned long long still_ok(char x)
{
return ((unsigned char)x) << 31;
}
unsigned long long incorrect(char x)
{
return ((unsigned char)x) << 32;
}
In simpler terms:
The shift operators promote their operands to int/unsigned int automatically. This is why your four byte version works: unsigned int is large enough for all your shifts. However, (in your implementation, as in most common ones) it can only hold 32 bits, and the compiler will not automatically choose a 64 bit type if you shift by more than 32 bits (that would be impossible for the compiler to know).
If you use large enough integral types for the shift operands, the shift will have the larger type as the result and the shifts will do what you expect.
If you turn on warnings, your compiler will probably also complain to you that you are shifting by more bits than the type has and thus always getting zero (see demonstration).
(The bit counts mentioned are of course implementation defined.)
A final note: Types beginning with double underscores (__) or underscore + capital letter are reserved for the implementation - using them is not technically "safe". Modern C++ provides you with types such as uint64_t that should have the stated number of bits - use those instead.
Your shift overflows bytes, and you are not printing the integers correctly.
This code is working:
(Take note of the print format and how the shifts are done in uint64_t)
#include <stdio.h>
#include <cstdint>
int main()
{
const unsigned char *command = (const unsigned char *)"\x42\xa0\x82\xa1\x21\x22";
uint64_t value=0;
for (int i=0; i<6; i++)
{
value <<= 8;
value += command[i];
}
printf("%x %x %x %x %x %x %llx",
command[0], command[1], command[2], command[3], command[4], command[5], value);
}

C++ - Getting size in bits of integer

I need to know whether an integer is 32 bits long or not (I want to know if it's exactly 32 bits long (8 hexadecimal characters). How could I achieve this in C++? Should I do this with the hexadecimal representation or with the unsigned int one?
My code is as follows:
mistream.open("myfile.txt");
if(mistream)
{
for(int i=0; i<longArray; i++)
{
mistream >> hex >> datos[i];
}
}
mistream.close();
Where mistream is of type ifstream, and datos is an unsigned int array
Thank you
std::numeric_limits<unsigned>::digits
is a static integer constant (or constexpr in C++11) giving the number of bits (since unsigned is stored in base 2, it gives binary digits).
You need to #include <limits> to get this, and you'll notice here that this gives the same value as Thomas' answer (while also being generalizable to other primitive types)
For reference (you changed your question after I answered), every integer of a given type (eg, unsigned) in a given program is exactly the same size.
What you're now asking is not the size of the integer in bits, because that never varies, but whether the top bit is set. You can test this trivially with
bool isTopBitSet(uint32_t v) {
return v & 0x80000000u;
}
(replace the unsigned hex literal with something like T{1} << (std::numeric_limits<T>::digits-1) if you want to generalise to unsigned T other than uint32_t).
As already hinted in a comment by #chux, you can use a combination of the sizeof operator and the CHAR_BIT macro constant. The former tells you (at compile-time) the size (in multiples of sizeof(char) aka bytes) of its argument type. The latter is the number of bits to the byte (usually 8).
You can encapsulate this nicely into a function template.
#include <climits> // CHAR_BIT
#include <cstddef> // std::size_t
#include <iostream> // std::cout, std::endl
template <typename T>
constexpr std::size_t
bit_size() noexcept
{
return sizeof(T) * CHAR_BIT;
}
int
main()
{
std::cout << bit_size<int>() << std::endl;
std::cout << bit_size<long>() << std::endl;
}
On my implementation, it outputs 32 and 64.
Since the function is a constexpr, you can use it in static contexts, such as in static_assert<bit_size<int>() >= 32, "too small");.
Try this:
#include <climits>
unsigned int bits_per_byte = CHAR_BIT;
unsigned int bits_per_integer = CHAR_BIT * sizeof(int);
The identifier CHAR_BIT represents the number of bits in a char.
The sizeof returns the number of char locations occupied by the integer.
Multiplying them gives us the number of bits for an integer.
OP said "if it's exactly 32 bits long (8 hexadecimal characters)" and further with ".. interested in knowing if the value is between power(2, 31) and power(2, 32) - 1". So it is a little fuzzy on negative 32-bit numbers.
Certainly OP wants to know the result based on the value and not the type.
bool integer_is_32_bits_long(int x) =
// cope with 32-bit int
((INT_MAX == 0x7FFFFFFF) && (x < 0)) ||
// larger 32-bit int
((INT_MAX > 0x7FFFFFFF) && (x >= 0x80000000) && (x <= 0xFFFFFFFF));
Of course if int is 16-bit, then the result is always false.
I want to know if it's exactly 32 bits long (8 hexadecimal characters)
I am interested in knowing if the value is between power(2, 31) and power(2, 32) - 1
So you want to know if the upper bit is set? Then you can simply test if the number is negative:
bool upperBitSet(int x)
{
return x < 0;
}
For unsigned numbers, you can simply shift left and back right and then check if you lost data:
bool upperBitSet(unsigned x)
{
return (x << 1 >> 1) != x;
}
The simplest way probably is to check if the 32nd bit is set:
bool isReally32bitsLong(uint32_t in) {
return (in >> 31)!=0;
}
bool isExactly32BitsLong(uint64_t in) {
return ((in >> 31)!=0) && ((in >> 32) == 0);
}

C++: sizeof of struct with bit fields

Why is gcc giving returning 13 as the sizeof of the following class ?
It seems to me that we should get e (4 bytes) + d (4 bytes) + 1 byte (for a and b) = 9 bytes. If it was alignment, aren't most 32 bit systems aligned on 8 byte boundaries ?
class A {
unsigned char a:1;
unsigned char b:4;
unsigned int d;
A* e;
} __attribute__((__packed__));
int main( int argc, char *argv[] )
{
cout << sizeof(A) << endl;
}
./a.out
13
You are very likely running on a 64 bit platform and the size of the pointer is not 4 but 8 bytes. Just do a sizeof on A * and print it out.
The actual size of structs with bitfields is implementation dependent, so whatever size gcc decides it to be would be right.

Unsigned long and bit shifting

I have a problem with bit shifting and unsigned longs. Here's my test code:
char header[4];
header[0] = 0x80;
header[1] = 0x00;
header[2] = 0x00;
header[3] = 0x00;
unsigned long l1 = 0x80000000UL;
unsigned long l2 = ((unsigned long) header[0] << 24) + ((unsigned long) header[1] << 16) + ((unsigned long) header[2] << 8) + (unsigned long) header[3];
cout << l1 << endl;
cout << l2 << endl;
I would expect l2 to also have a value of 2147483648 but instead it prints 18446744071562067968. I assume the bit shifting of the first byte causes problems?
Hopefully somebody can explain why this fails and how I modify the calculation of l2 so that it returns the correct value.
Thanks in advance.
Your value of 0x80 stored in a char is a signed quantity. When you cast this into a wider type, the value is being signed extended to keep the same value as a larger type.
Change the type of char in the first line to unsigned char and you will not get the sign extension happening.
To simplify what is happening in your case, run this:
char c = 0x80
unsigned long l = c
cout << l << endl;
You get this output:
18446744073709551488
which is -128 as a 64-bit integer (0x80 is -128 as a 8-bit integer).
Same result here (Linux/x86-64, GCC 4.4.5). The behavior depends on the size of unsigned long, which is at least 32 bits, but may be larger.
If you want exactly 32 bits, use a uint32_t instead (from the header <stdint.h>; not in C++03 but in the upcoming standard and widely supported).