Can you tell me the best way to reserve for example 1000 bits from memory in C?
I'm doing a program and i need to manage flags (values =0 or =1). What is the most efficient way to do that?
I was thinking in reserve the space needed and control the flags (bits) using masks.
Thank you
The least amount of memory you can access/address in C is a byte which is of CHAR_BIT bits width (which is guranteed to be at least 8 bits long). So, if you are looking for a packed structure you could use ceil(1000/8) bytes.
You may want to take a look at this SO question for bit manipulation details.
You can use the bool type:
#include <stdbool.h> // for bool
#include <stdlib.h> // for malloc
#define N 1000
bool *b = malloc(N * sizeof *b);
// for example to set the 42th element to 1
b[41] = 1;
something like?
struct bitf
{
unsigned char b:1;
};
struct bitf[1000];
if you won't to use bitmask the max size is the max size of a variable on your computer.
Error trying to define a 1,024-bit (128 Byte) Bit Field
or for min memory:
#include <stdio.h>
int main(void)
{
struct bitf
{
unsigned char a:1;
unsigned char b:1;
unsigned char c:1;
unsigned char d:1;
unsigned char e:1;
unsigned char f:1;
unsigned char g:1;
unsigned char h:1;
};
struct bitf number[125];
number[100].a = 1;
number[110].h =1;
printf("size: %d a:%d h:%d\n",sizeof(number), number[100].a ==0, number[110].h ==1);
return 0;
}
output:
size: 125 a:0 h:1
Related
For some reason that i cant quite figure out my union of just structs containing bit fields is setting up twice as many bytes as is are necessary for any single struct.
#include <stdio.h>
#include <stdlib.h>
union instructionSet {
struct Brane{
unsigned int opcode: 4;
unsigned int address: 12;
} brane;
struct Cmp{
unsigned int opcode: 4;
unsigned int blank: 1;
unsigned int rsvd: 3;
unsigned char letter: 8;
} cmp;
struct {
unsigned int rsvd: 16;
} reserved;
};
int main() {
union instructionSet IR;// = (union instructionSet*)calloc(1, 2);
printf("size of union %ld\n", sizeof(union instructionSet));
printf("size of reserved %ld\n", sizeof(IR.reserved));
printf("size of brane %ld\n", sizeof(IR.brane));
printf("size of brane %ld\n", sizeof(IR.cmp));
return 0;
}
All of the calls to sizeof return 4 however to my knowledge they should be returning 2.
There are a couple of problems here, first of all, your bitfield Brane is using unsigned int which is 4 byte.
Even if you just use half of the bits, you still use a full 32-bit width unsigned int.
Second, your Cmp bitfields uses two different field types, so you use 8-bit of the 32-bit unsigned int for your first 3 fields, and then you use a unsigned char for it's full 8-bit.
Because of data alignement rules, this structure would be at least 6 bytes, but potentially more.
If you wanted to optimize the size of your union to only take 16-bit. Your first need to use unsigned short and then you need to always use the same field type to keep everything in the same space.
Something like this would fully optimize your union:
union instructionSet {
struct Brane{
unsigned short opcode: 4;
unsigned short address: 12;
} brane;
struct Cmp{
unsigned short opcode: 4;
unsigned short blank: 1;
unsigned short rsvd: 3;
unsigned short letter: 8;
} cmp;
struct {
unsigned short rsvd: 16;
} reserved;
};
This would give you a size of 2 all around.
C 2018 6.7.2.1 11 allows the C implementation to choose the size of the container is uses for bit-fields:
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. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined.…
The implementation you are using apparently chooses to use four-byte units. Likely that is also the size of an int in the implementation, suggesting that it is a convenient size for the implementation.
It isn't specified what this code will do and it isn't meaningful to reason about it without a specific system and compiler in mind. Bit-fields are simply too poorly specified in the standard to be reliably used for things like memory layouts.
union instructionSet {
/* any number of padding bits may be inserted here */
/* we don't know if what will follow is MSB or LSB */
struct Brane{
unsigned int opcode: 4;
unsigned int address: 12;
} brane;
struct Cmp{
unsigned int opcode: 4;
unsigned int blank: 1;
unsigned int rsvd: 3;
/* anything can happen here, "letter" can merge with the previous
storage unit or get placed in a new storage unit */
unsigned char letter: 8; // unsigned char does not need to be supported
} cmp;
struct {
unsigned int rsvd: 16;
} reserved;
/* any number of padding bits may be inserted here */
};
The standard lets the compiler pick a "storage unit" for any bit-field type, which can be of any size. The standard simply states:
An implementation may allocate any addressable storage unit large enough to hold a bitfield.
Things we can't know:
How large the bitfields of type unsigned int are. 32 bits might make sense but no guarantee.
If unsigned char is allowed for bit-fields.
How large the bitfields of type unsigned char are. Could be any size from 8 to 32.
What will happen if the compiler picked a smaller storage unit than the expected 32 bits, and the bits doesn't fit inside it.
What happens if an unsigned int bit-field meets an unsigned char bit-field.
If there will be padding in the end of the union or in the beginning (alignment).
How individual storage units within the structs are aligned.
The location of the MSB.
Things we can know:
We have created some sort of binary blob in memory.
The first byte of the blob resides on the least significant address in memory. It may contain data or padding.
Further knowledge can be obtained by having a very specific system and compiler in mind.
Instead of the bit-fields we can use 100% portable and deterministic bitwise operations, that yield the same machine code anyway.
Read about memory structure padding / memory alignment. By default 32bit processor read from memory by 32bit (4bytes) because is faster. So in memory char + uint32 will be write on 4 + 4 = 8 bytes (1byte - char, 3bytes space, 4bytes uint32).
Add those lines on begin and end of your program and will be result 2.
#pragma pack(1)
#pragma unpack
This is way to say to the compiler: align memory to 1 byte (by default 4 on 32bit processor).
PS: try this example with different #pragma pack set:
struct s1
{
char a;
char b;
int c;
};
struct s2
{
char b;
int c;
char a;
};
int main() {
printf("size of s1 %ld\n", sizeof(struct s1));
printf("size of s2 %ld\n", sizeof(struct s2));
return 0;
}
I have a buffer where each entry in the buffer is 8 bits in size:
uint8_t Buffer[10] = {0x12,0x34,0x56,0x78,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6};
What I need to do is to create pointers to that array, for example 16 bit and 32 bit pointers. For example:
uint32_t *x;
x = Buffer;
uint32_t *y;
y = Buffer+4;
uint16_t *z;
z = Buffer+8;
Where each variable would then read from the array, for example:
x = 0x78563412
y = 0xf4f3f2f1
z = 0xf6f5
This works completely fine, the problem is that I'm getting warnings about incompatible pointer types. So I was wondering if there is an alternative way of doing this or if I'll just have to live with the warnings? Or am I simply doing this completely the wrong way?
Please note that this code will be executed on a single type of platform where the endianness is always the same and the size of data types is always the same.
You should heed the warnings; what you're doing is undefined behavior. Type aliasing like that is undefined behavior, particularly since there is no guarantee that Buffer has the correct alignment such that it can be accessed as an int/short. If Buffer has the correct alignment, then you can just explicitly cast and it's okay (and the warning will go away).
You have two options:
One, you align the buffer as the larger of the two types. Be careful that your pointer arithmetic doesn't throw off the alignment:
#include <stdalign.h>
alignas(int) unsigned char Buffer[10] = {0x12,0x34,0x56,0x78,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6};
unsigned int *x;
x = (unsigned int*)(Buffer);
unsigned int *y;
y = (unsigned int*)(Buffer+4);
unsigned short *z;
z = (unsigned short*)(Buffer+8);
Two, you create an unsigned int/unsigned short variable and then memcpy the bytes you're interested in into the variable:
unsigned int x;
memcpy(&x, Buffer, 4);
unsigned int y;
memcpy(&y, Buffer + 4, 4);
unsigned short z;
memcpy(&z, Buffer + 8, 2);
The problem with your approach is that it assumes a particular endianness of underlying hardware. Different computers will interpret a sequence of hex bytes
01 23 45 67
as eiter
01234567 or 67452301
Your program may compile and run on both systems, but since the result is hardware-specific, the compiler must warn you of the possibility.
The proper way of forcing a particular endianness is by using an array of integers, convert them using hton and ntoh functions, and set individual bytes either directly by casting a pointer to unsigned char*, or with memcpy.
You might want to use a union
#include <stdint.h>
#include <stdio.h>
typedef union{
uint8_t Buffer[10];
struct{
uint32_t x;
uint32_t y;
uint16_t z;
};
}MYSTRUCT;
int main(){
MYSTRUCT b = {0x12,0x34,0x56,0x78,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6};
printf("x=%#x y=%#x z=%#x\n",b.x,b.y,b.z);
return 0;
}
I'm using libpcap to analyze and process packets. I have to compare two arrays of unsigned chars, take the difference and save it to a hashtable. Another thread will periodically scans across the hashtable and compute for average,standard deviation, max and min.
My question is the following, what would be the most efficient way to perform subtraction on two arrays?
For example:
A="0x34 0x44 0x59 0x5B"
B="0x34 0x42 0x43 0x43"
My first thought is to convert it to an integer, by converting the array into an array of signed chars, doing take requires a function to perform lookup function. Because this is function is called for every packet received on the system.
use the union can make this simple, because different data types share the same memory, we can then use this feature to convert data type.
note the Little-endian
#include <stdio.h>
typedef union new_array{
struct array {
unsigned char f4;
unsigned char f3;
unsigned char f2;
unsigned char f1;
}array;
unsigned int int_array;
}new_array;
int main()
{
new_array A, B;
A.array.f1 = 0x34;
A.array.f2 = 0x44;
A.array.f3 = 0x59;
A.array.f4 = 0x5B;
B.array.f1 = 0x34;
B.array.f2 = 0x42;
B.array.f3 = 0x43;
B.array.f4 = 0x43;
printf("%u\n", A.int_array - B.int_array);
}
I have written this program:
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
struct A {
bool a;
bool b;
bool c;
bool d;
};
struct B {
int a;
};
int main() {
struct A* pa = malloc( sizeof(struct A) );
struct B* pb = (struct B*) pa;
pa->a = 0;
pa->b = 1;
pa->c = 0;
pa->d = 0;
printf("value of pint is %i\n", pb->a);
return 0;
}
I expect that it print 2 (0010) but the output is 256. Any one cloud help that what is wrong with this code?
I expect that it print 2 (0010) but the output is 256. Any one cloud help that what is wrong with this code?
A bool takes up at least one byte. In your case, apparently exactly one byte, and your platform is little-endian (with 8-bit char). So the second (least significant) byte is 1, all other bytes 0, makes 1*256.
Note that the type-punning via pa and pb violates strict aliasing.
Use a union to portably type-pun.
After you initialize pa, you have
*pa = { 0x00, 0x01, 0x00, 0x00 }
since each bool is one byte. And when you type cast this into an int value, you get (in little endian machine) *pb as
*pb = 0x00000100
which is obviously 256. Got it?
If you want, you may define struct A as:
struct A {
bool a:1;
bool b:1;
bool c:1;
bool d:1;
};
but do not typecast a pointer of struct A to that of struct B since both structures's sizes are then different.
This may be helpful to you in future:
union A {
struct {
bool bit0:1;
bool bit1:1;
bool bit2:1;
bool bit3:1;
bool bit4:1;
bool bit5:1;
bool bit6:1;
bool bit7:1;
};
unsigned char cByte;
};
By defining so, you can access this as bit-wise or byte-wise.
%i prints an integer.
bool is an unsigned integer type large enough to store the values 0 and 1.
You can print a bool this way:
printf("%d\n", b);
You are printing the number in little Endian notation. Effectively, what you printed is:
0 * 256^0 + 1 * 256^1 + 0 * 256^2 + 0 * 256^3
If you decide to use bitfields (as suggested by someone else), you should use %x to print in hexadecimal. If you strictly want to print in binary, you will have to do it using a loop going over individual bits.
Try
struct A {
bool a:1;
bool b:1;
bool c:1;
bool d:1;
};
the :1 part force compiler alloc 1 bit instead of 1 byte for each member variable, so the memory layout of struct A will look like this one (assume little endian):
|-byte 1-|-byte 2-|-byte 3-|-byte 3-|
uuuudcba uuuuuuuu uuuuuuuu uuuuuuuu
where u donates for unused. when cast it to integer, you will get an integer view of:
uuuuuuuu uuuuuuuu uuuuuuuu uuuudcba
And because of different bit-order of different compiler implementation, you may get also get reversed result 4 (0100) instead of 2 (0010)
It was my understanding that the type for the bit field declarator should be of some int type. In fact, here is the line from the C99 standard
"A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed >int, unsigned int, or some other implementation-defined type."
However, I came across some code today which shows an enum as the type, like this.
typedef enum
{
a = 0,
b = 1
}ENUM;
typedef struct
{
ENUM id : 8;
}STRUCT;
Without comments or documentation, it's hard to tell the intent. Could anyone provide some insight?
a and b are both of the int type, signed int. It has a length of 32 bit, meaning 4 Byte.
But the enum ENUM does not need that much.
0000000000000000000000000000000 equals a
0000000000000000000000000000001 equals b
So the creator thought making the ENUM shorter than int with a bitfield of the length of 8 bit, minimum length 1 Byte.
00000000 or 00000001
He could have taken the char type from the beginning with the length of 1 Byte though.
On some compilers you can activate a feature to ensure an enum can be smaller than int. Using the option --short-enums of GCC, makes it use the smallest type still fitting all the values.
Here is an example how you would save memory with a bitfield.
You see the someBits struct is smaller than twoInts struct.
#include "stdio.h"
struct oneInt {
int x;
};
struct twoInts {
int x;
int y;
};
struct someBits {
int x:2; // 2 Bits
int y:6; // 6 Bits
};
int main (int argc, char** argv) {
printf("type int = %lu Bytes\n", sizeof(int));
printf("oneInt = %lu Bytes\n", sizeof(struct oneInt));
printf("twoInts = %lu Bytes\n", sizeof(struct twoInts));
printf("someBits = %lu Bytes\n", sizeof(struct someBits));
return 0;
}
Output:
type int = 4 Bytes
oneInt = 4 Bytes
twoInts = 8 Bytes
someBits = 4 Bytes