The VS documentation states
Half the size of a pointer. Use within a structure that contains a pointer and two small fields.
Windows Data Types
What, exactly, is this type and how is it used, if ever?
Note: Anonymous structs are not standard, but MSVC takes them:
union
{
int * aPointer
struct
{
HALF_PTR lowerBits;
HALF_PTR upperBits;
};
} myvar; //You can be assured this union is sizeof(int *)
If you're thinking they're not too terribly useful, you would be right.
I found this article on Intel's site, and it they suggest using it in a context where you have a class with many pointer members, along with a 32-bit offset to get the actual address, to cut down on data bloat of a class. The article specifically talks about the Itanium platform because it uses 64-bit pointers instead of 32-bit, but I assume the problem/solution to the problem would be the same on any system using 64-bit pointers.
So in short, it seems to suggest that it can be used if you, for example, wish to reduce the memory footprint of a class?
Use within a structure that contains a pointer and two small fields.
This means that in the following structure, no padding is required:
struct Example {
void* pointer;
HALF_PTR one;
HALF_PTR two;
};
Of course, this is only relevant if the size of HALF_PTR (32 bits on a 64-bit system, 16 bits on a 32-bit system) is sufficient to hold the intended values.
I guess “Use within a structure that contains a pointer and two small fields” means a pointer constructed from two HALF_PTRs along with two other non-pointer small data fields
struct Packed {
HALF_PTR low_ptr;
HALF_PTR high_ptr;
SMALL one;
SMALL two;
};
struct Padded {
void *ptr;
SMALL one;
SMALL two;
};
On 32-bit Windows:
When SMALL is char: sizeof(Packed) == 6 but sizeof(Padded) = 8
When SMALL is short: the size of both structs are 8, but the alignment requirement for the former is just 2 compared to 4
On 64-bit Windows:
When SMALL is char: sizeof(Packed) == 10 but sizeof(Padded) = 16
When SMALL is short: sizeof(Packed) == 12 but sizeof(Padded) = 16
When SMALL is int: same size, but reduced alignment requirement like above
This is unlike Philipp's answer where the size and alignment of the struct is exactly the same whether splitting into half or not
struct Example1 {
void* pointer;
HALF_PTR one;
HALF_PTR two;
};
struct Example2 {
void* pointer;
void* one_two;
};
Both have alignment equal to the size of the pointer, and size of 2 pointers
Related
#include <iostream>
using namespace std;
typedef union {
long i;
int k[5];
char c;
} UDATE;
struct data {
int cat;
UDATE cow;
double dog;
} too;
UDATE temp;
int main()
{
cout << sizeof(struct data)+sizeof(temp) << endl;
return 0;
}
under ubuntu 18.04, the answer to this question is 64, but I want to know how uDATE cow in struct is stored in memory, or the rules of data storage?
According to the C++ standard:
The size of a union is sufficient to contain the
largest of its data members. Each data member is allocated as if it
were the sole member of a struct.
So the memory layout of the union is the same as if you had a long there, an array of 5 ints there, or a char there, but spaced to the largest of these (the array of ints). I presume you're using GCC, and IIRC GCC sets a size of 32-bits for int even on a 64-bit architecture. UDATE would therefore have a size of 20-bytes. You'd naively expect, therefore, sizeof(struct data) + sizeof(temp) to return 52. The fact that you're apparently getting 64 is probably because GCC is aligning things to 64-bit boundaries and thus taking 24-bytes for UDATE, and inserting a 4-byte spacer between cat and cow in your data struct.
Note that the standard makes no guarantees made about type-punning - that is the frequently used low level technique where the union is written using one method and read using another to, for example, access the bytes that make up an integer - and claims that a union may only be accessed using the same entries that it was written using (baring an exception for a union of POD structs that share common initial members). However, in practice every compiler I've ever used will read the memory in the manner you'd expect if you'd simply cast a pointer from one type to another in the union using a reinterpret or C-style cast.
Is bitfield a C concept or C++?
Can it be used only within a structure? What are the other places we can use them?
AFAIK, bitfields are special structure variables that occupy the memory only for specified no. of bits. It is useful in saving memory and nothing else. Am I correct?
I coded a small program to understand the usage of bitfields - But, I think it is not working as expected. I expect the size of the below structure to be 1+4+2 = 7 bytes (considering the size of unsigned int is 4 bytes on my machine), But to my surprise it turns out to be 12 bytes (4+4+4). Can anyone let me know why?
#include <stdio.h>
struct s{
unsigned int a:1;
unsigned int b;
unsigned int c:2;
};
int main()
{
printf("sizeof struct s = %d bytes \n",sizeof(struct s));
return 0;
}
OUTPUT:
sizeof struct s = 12 bytes
Because a and c are not contiguous, they each reserve a full int's worth of memory space. If you move a and c together, the size of the struct becomes 8 bytes.
Moreover, you are telling the compiler that you want a to occupy only 1 bit, not 1 byte. So even though a and c next to each other should occupy only 3 bits total (still under a single byte), the combination of a and c still become word-aligned in memory on your 32-bit machine, hence occupying a full 4 bytes in addition to the int b.
Similarly, you would find that
struct s{
unsigned int b;
short s1;
short s2;
};
occupies 8 bytes, while
struct s{
short s1;
unsigned int b;
short s2;
};
occupies 12 bytes because in the latter case, the two shorts each sit in their own 32-bit alignment.
1) They originated in C, but are part of C++ too, unfortunately.
2) Yes, or within a class in C++.
3) As well as saving memory, they can be used for some forms of bit twiddling. However, both memory saving and twiddling are inherently implementation dependent - if you want to write portable software, avoid bit fields.
Its C.
Your comiler has rounded the memory allocation to 12 bytes for alignment purposes. Most computer memory syubsystems can't handle byte addressing.
Your program is working exactly as I'd expect. The compiler allocates adjacent bitfields into the same memory word, but yours are separated by a non-bitfield.
Move the bitfields next to each other and you'll probably get 8, which is the size of two ints on your machine. The bitfields would be packed into one int. This is compiler specific, however.
Bitfields are useful for saving space, but not much else.
Bitfields are widely used in firmware to map different fields in registers. This save a lot of manual bitwise operations which would have been necessary to read / write fields without it.
One disadvantage is you can't take address of bitfields.
I'm porting an application from 32 bit to 64 bit.
It is C style coding (legacy product) although it is C++. I have an issue where a combination of union and struct are used to store values. Here a custom datatype called "Any" is used that should hold data of any basic datatype. The implementation of Any is as follows:
typedef struct typedvalue
{
long data; // to hold all other types of 4 bytes or less
short id; // this tells what type "data" is holding
short sign; // this differentiates the double value from the rest
}typedvalue;
typedef union Any
{
double any_any;
double any_double; // to hold double value
typedvalue any_typedvalue;
}Any;
The union is of size 8 bytes. They have used union so that at a given time there will only be one value and they have used struct to differentiate the type. You can store a double, long, string, char, float and int values at any given time. Thats the idea.
If its a double value, the value is stored in any_double. if its any other type, then its stored in "data" and the type of the value is stored in the "id". The "sign" would tell if value "Any" is holding a double or another type.
any_any is used liberally in the code to copy the value in the address space irrespective of the type. (This is our biggest problem since we do not know at a given time what it will hold!)
If its a string or pointer "Any" is suppose to hold, it is stored in "data" (which is of type long). In 64 bit, here is where the problem lies. pointers are 8 bytes. So we will need to change the "long" to an equivalent 8 byte (long long). But then that would increase the size of the union to 16 bytes and the liberal usage of "any_any" will cause problems. There are too many usage of "any_any" and you are never sure what it can hold.
I already tried these steps and it turned unsuccessful:
1. Changed the "long data" to "long long data" in the struct, this will make the size of the union to 16 bytes. - This will not allow the data to be passed as "any_any" (8 bytes).
2. Declared the struct as a pointer inside union. And changed the "long data" to "long long data" inside struct. - the issue encountered here was that, since its a pointer we need to allocate memory for the struct. The liberal use of "any_any" makes it difficult for us to allocate memory. Sometimes we might overwrite the memory and hence erase the value.
3. Create a separate collection that will hold the value for "data" (a key value pair). - This will not work because this implementation is at the core of application, the collection will run into millions of data.
Can anybody help me in this?
"Can anybody help me" this sounds like a cry of desperation, and I totally understand it.
Whoever wrote this code had absolutely no respect for future-proofing, or of portability, and now you're paying the price.
(Let this be a lesson to anyone who says "but our platform is 32bit! we will never use 64bit!")
I know you're going to say "but the codebase is too big", but you are better off rewriting the product. And do it properly this time!
Ignoring that fact that the original design is insane, you could use <stdint.h> (or soon <cstdint> to get a little bit of predictability:
struct typedvalue
{
uint16_t id;
uint16_t sign;
uint32_t data;
};
union any
{
char any_raw[8];
double any_double
typedvalue any_typedvalue;
};
You're still not guaranteed that typedvalue will be tightly packed, since there are no alignment guarantees for non-char members. You could make a struct Foo { char x[8]; }; and type-pun your way around, like *(uint32_t*)(&Foo.x[0]) and *(uint16_t*)(&Foo.x[4]) if you must, but that too would be extremely ugly.
If you are in C++0x, I would definitely throw in a static assertion somewhere for sizeof(typedvalue) == sizeof(double).
If you need to store both an 8 byte pointer and a "type" field then you have no choice but to use at least 9 bytes, and on a 64-bit system alignment will likely pad that out to 16 bytes.
Your data structure should look something like:
typedef struct {
union {
void *any_pointer;
double any_double;
long any_long;
int any_int;
} any;
char my_type;
} any;
If using C++0x consider using a strongly typed enumeration for the my_type field. In earlier versions the storage required for an enum is implementation dependent and likely to be more than one byte.
To save memory you could use (compiler specific) directives to request optimal packing of the data structure, but the resulting mis-aligned memory accesses may cause performance issues.
So, you know how the primitive of type char has the size of 1 byte? How would I make a primitive with a custom size? So like instead of an in int with the size of 4 bytes I make one with size of lets say 16.
Is there a way to do this? Is there a way around it?
It depends on why you are doing this. Usually, you can't use types of less than 8 bits, because that is the addressable unit for the architecture. You can use structs, however, to define different lengths:
struct s {
unsigned int a : 4; // a is 4 bits
unsigned int b : 4; // b is 4 bits
unsigned int c : 16; // c is 16 bits
};
However, there is no guarantee that the struct will be 24 bits long. Also, this can cause endian issues. Where you can, it's best to use system independent types, such as uint16_t, etc. You can also use bitwise operators and bit shifts to twiddle things very specifically.
Normally you'd just make a struct that represents the data in which you're interested. If it's 16 bytes of data, either it's an aggregate of a number of smaller types or you're working on a processor that has a native 16-byte integral type.
If you're trying to represent extremely large numbers, you may need to find a special library that handles arbitrarily-sized numbers.
In C++11, there is an excellent solution for this: std::aligned_storage.
#include <memory>
#include <type_traits>
int main()
{
typedef typename std::aligned_storage<sizeof(int)>::type memory_type;
memory_type i;
reinterpret_cast<int&>(i) = 5;
std::cout << reinterpret_cast<int&>(i) << std::endl;
return 0;
}
It allows you to declare a block of uninitialized storage on the stack.
If you want to make a new type, typedef it. If you want it to be 16-bytes in size, typedef a struct that has 16-bytes of member data within it. Just beware that quite often compilers will pad things on you to match your systems alignment needs. A 1 byte struct rarely remains 1 bytes without care.
You could just static cast to and from std::string. I don't know enough C++ to give an example, but I think this would be pretty intuitive.
I am curious to know why bit fields with same data type takes less size than with mixed
data types.
struct xyz
{
int x : 1;
int y : 1;
int z : 1;
};
struct abc
{
char x : 1;
int y : 1;
bool z : 1;
};
sizeof(xyz) = 4
sizeof(abc) = 12.
I am using VS 2005, 64bit x86 machine.
A bit machine/compiler level answer would be great.
Alignment.
Your compiler is going to align variables in a way that makes sense for your architecture. In your case, char, int, and bool are different sizes, so it will go by that information rather than your bit field hints.
There was some discussion in this question on the matter.
The solution is to give #pragma directives or __attributes__ to your compiler to instruct it to ignore alignment optimizations.
The C standard (1999 version, §6.7.2.1, page 102, point 10) says this:
An implementation may allocate any addressable storage unit large enough to hold a
bit-field. If enough space remains, a bit-field that immediately follows another
bit-field in a structure shall be packed into adjacent bits of the same unit.
There does not seem to be any wording to allow the packing to be affected by the types of the fields. Thus I would conclude that this is a compiler bug.
gcc makes a 4 byte struct in either case, on both a 32-bit and a 64-bit machine, under Linux. I don't have VS and can't test that.
It's complier bug or some code error.
All bits assigned in the structure always try to make sizeof highest data type defined.
e.g. In struct xyz sizeof highest data type is 4 i.e. of int.
In the similar fashion for second structure abc highest data type size is 4 for int.
Where as if we change variables of structure as following:
struct abc
{
char a:1;
char b:1;
bool c:1;
};
sizeof(abc) would be 1 not 4. Since size highest data type is 1 and all bits fit into 1byte of char.
various tests could be performed by changing data type in the structure.
Link for output based on old structure:
Visit http://codepad.org/6j5z2CEX
Link for output based on above structure defined by me:
Visit http://codepad.org/fqF9Ob8W
To avoid such problems for sizeof structures we shall properly pack structures using #pragma pack macro.