How to "mark" pointers by setting the last bit to 1? - c

I am trying to mark and unmark pointers so I can implement Non-Blocking linked lists. I checked that on my architecture the last bit is never used, so I am trying to use change it to mark/unmark pointers.
I am trying to perform an OR to set the last bit to 1, an AND to unset it and an AND to check if it is set to 1.
The problem is that when I perform bitwise (the commented Macros) operations on a pointer I cannot dereference it. Dereferencing it results in a segmentation fault even though the integer value of the pointer is correct.
More specifically, the #define unmark(x) (x & (uintptr_t) 0xfffffffe) is what is causing the segmentation fault. If I do not use it (and use #define unmark(x) x - 1 instead) the program works.
Incrementing and decrementing the pointer seems to be working, but it may make the solution architecture specific. This is because on my architecture pointers always end in 8, which has the final bit set to 0. If this is not the case my solution would not be very portable.
I understand that manipulating pointers is probably not portable anyway, but it is required for this algorithm. If someone knows what is causing the problem it would be fantastic.
This is the code I have used to test the solution:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
//This produces segfault, for some reason
//#define unmark(x) (x & (uintptr_t) 0xfffffffe)
//#define mark(x) (x | (uintptr_t) 0x00000001)
#define is_marked(x) ((long) x & 0x00000001)
#define mark(x) x + 1
#define unmark(x) x - 1
struct Example {
long x;
long y;
};
int main() {
struct Example *x = malloc(sizeof(struct Example));
x->x = 10;
x->y = 20;
uintptr_t p = (uintptr_t)(void*) x;
printf("%ld\n", ((struct Example *) (void*) p)->y);
printf("%04x\n", p);
printf("Is marked: %d\n", is_marked(p));
p = mark(p);
printf("%04x\n", p);
printf("Is marked: %d\n", is_marked(p));
p = unmark(p);
printf("%04x\n", p);
printf("Is marked: %d\n", is_marked(p));
printf("%ld\n", ((struct Example *) (void*) p)->y);
return 0;
}

Code has many problems
Not clearing just the least significant bit
x & (uintptr_t) 0xfffffffe assumes uintptr_t is 32-bit. Better as
#define unmark(x) ((x) & ~(uintptr_t)1)
// or
#define unmark(x) (((x) | 1) ^ 1)
Assuming bit manipulation of pointers is OK
Mis-matched specifier
// printf("%04x\n", p);
printf("%04jx\n", (uintmax_t) p);
// printf("Is marked: %d\n", is_marked(p));
// Unclear correct specifier.
Better as
// #define is_marked(x) ((long) x & 0x00000001)
#define is_marked(x) (!!((x) & 1))
Unneeded casts
//#define mark(x) (x | (uintptr_t) 0x00000001)
#define mark(x) ((x) | 1)

Related

Circular buffer increment using alternate method

I am not able to understand how does the last statement increments the pointer.Can somebody explain me with few examples?
The code, as shown:
aptr = (aptr + 1) & (void *)(BUFFERSIZE - 1);
// |________| incremented here
Since it is a circular buffer AND the buffer size is a power of 2, then the & is an easy and fast way to roll over by simply masking. Assuming that the BUFFERSIZE is 256, then:
num & (256 - 1) == num % 256
num & (0x100 - 1) == num % 0x100
num & (0x0ff) == num % 0x100
When the number is not a power of 2, then you can't use the masking technique:
num & (257 - 1) != num % 257
num & (0x101 - 1) != num % 0x101
num & 0x100 != num % 0x101
The (void *) allows the compiler to choose an appropriate width for the BUFFERSIZE constant based on your pointer width... although it is generally best to know - and use! - the width before a statement like this.
I added the hex notation so to make more clear why the & results in an emulated rollover event. Note that 0xff is binary 0x11111111, so the AND operation is simply masking off the upper bits.
2 problems with this approach.
A) Using a pointer with a bit-wise operation is not portable code. #Ilja Everilä
char *aptr;
// error: invalid operands to binary & (have 'char *' and 'void *')
// The following increments the index: (not really)
// aptr = (aptr + 1) & (void *)(BUFFERSIZE-1);
B) With compilers that support the non-standard math on a void * akin to a char *, the math is wrong if aptr point to an object wider than char and BUFFERSIZE is the number of elements in the buffer and not the byte-size. Of course this depends on how the non-standard complier implements some_type * & void *. Why bother to unnecessarily code to use some implementation specific behavior?
Instead use i % BUFFERSIZE. This portable approach works when BUFFERSIZE is a power-of-2 and well as when it is not. When a compiler sees i % power-of-2 and i is some unsigned type, then the same code is certainly emitted as i & (power-of-2 - 1).
For compilers that do not recognize this optimization, then one should consider a better compiler.
#define BUFFERSIZE 256
int main(void) {
char buf[BUFFERSIZE];
// pointer solution
char *aptr = buf;
aptr = &buf[(aptr - buf + 1) % BUFFERSIZE];
// index solution
size_t index = 0;
index = (index + 1) % BUFFERSIZE;
}

Shift operator on integers

I have the following function:
#include<stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdint.h>
#include <inttypes.h>
uint64_t dtally(uint64_t x)
{
uint64_t t = 0;
while (x){ t += 1 << ((x%10) * 6), x /= 10;
return t;
}
int main(int argc, char *argv[])
{
printf("%" PRIu64 "\n", dtally(39));
return 0;
}
when I pass a number as 39 i understand should return the following value
18014398509481984
but it returns this value:
4456448
because returns this value and not what you expected?
There are two problem with your code (in fact it is the same problem twice).
First, t is an int, which is usually a 32 bit integer (and at least 16 bits). So 2^54, will not fit there. You have to use a 64 bit type for t. But your problem will persist.
The second problem is trickier: 1 << ((x % 10) * 6) perform a shift operation on the literal 1. But 1 is an int. So 1 << 54 will return 0 (the one is shifted out of the 32 bits of memory, then added to t). To solve this, you can cast the literal 1 to int64_t or use the literal 1LL (type long long) instead.
So you should have something like this:
int count(int x)
{
int64_t t = 0;
while (x) t += 1LL << ((x % 10) * 6), x /= 10;
return t;
}
18014398509481984 is probably too big for an int on your platform.
Check this by testing sizeof(int). If that's 4 then the largest number you can represent is a little over 2 billion. It might even be only 2 (in which case the largest int would be 32767).
You could use int64_t instead which is 64 bits (and available since C99; although a platform is not compelled to support it).
Don't forget to suffix any literals with LL which denotes a 64 bit type.

REPEAT_BYTE(x) macro

I was looking the code in kernel.h header file in /usr/src/linux-headers-3.11-.../include/linux/, I stumbled upon this macro (line 47) :
#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
After running this example I made:
#include <stdio.h>
#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
int main(void)
{
long z = 12;
fprintf(stderr, "\tz = %ldd (0x%lX)\n"
"\tREPEAT_BYTE(%ldd) = %ldd (0x%lX)\n",
z, z, z, REPEAT_BYTE(z), REPEAT_BYTE(z));
return 0;
}
I've figured out what it does: It receives an int between 0 and 255(including them), so any one-byte long int, and it repeats that byte. This is obvious (except macro's name) when looking at the output:
z = 12d (0xC)
REPEAT_BYTE(12d) = 868082074056920076d (0xC0C0C0C0C0C0C0C)
However, I still can't understand how does this expression work: ((~0ul / 0xff) * (x)), I could use some help with it.
Thanks a lot in advance!
On a 64-bit machine, ~0ul is 0xffffffffffffffff. Divide that by 0xff and you get 0x0101010101010101. Multiply by an 8-bit value and you get that 8-bit value repeated 8 times.

Union and endianness

typedef union status
{
int nri;
char cit[2];
}Status;
int main() {
Status s;
s.nri = 1;
printf("%d \n",s.nri);
printf("%d,%d,\n",s.cit[0],s.cit[1]);
}
OUTPUT:
1
0,1
I know this output on the second line is depend on the endianess of the CPU. How I can write such in a platform-independant program? Is there any way of checking the endianess of the CPU?
You can use htonl() and/or ntohl(). htonl() stands for "host to network long", while ntohl() stands for "network to host long". The "host" and "network" refers to the byte order. Network byte order is "big-endian". The operations will be no-ops if the host platform is also "big-endian". Using these routines, the following program will always report the same output:
uint32_t x = htonl(1);
unsigned char *p = (void *)&x;
printf("%u %u %u %u\n", p[0], p[1], p[2], p[3]);
uint32_t y = ntohl(x);
assert(y == 1);
If you want endian-independent code, then you want platform-indepentent code as well, otherwise your requirements don't make sense. Code which does not rely on endianess cannot rely of the size of an int, nor on the signedness of char.
To get something truly portable, I suppose you would have to write something similar to this:
#include <stdio.h>
#include <stdint.h>
#define INT_BITS (sizeof(int) * 8)
#define BYTE0_MASK (0xFFu << (INT_BITS - 8))
#define BYTE1_MASK (0xFFu << (INT_BITS - 16))
int main()
{
int i = 0xAABBCCDD;
unsigned char arr [2] =
{
(i & BYTE0_MASK) >> (INT_BITS - 8),
(i & BYTE1_MASK) >> (INT_BITS - 16)
};
printf("%x %x", arr[0], arr[1]);
}
Endianness is usually not an issue if your program does not communicate with other program (including the same program written for another platform), unless you do something very special like the union defined in your question. When your program does communicate with other programs, like saving binary data into a file, sending data in a socket, it'd be better to define the endianness clearly in the format/protocol. Alternatively you can also transmit the data in textual form.

Defining smallest possible sized macro in C

I want to define a boolean macro in C that uses less than 4 bytes. I have looked into this, and maybe it is possible to define an asm macro, with gcc, that could be less. It is important that the definition will be small because I will have tens of thousands of matrices which hold these boolean values, and it is important that they can be as memory efficient as possible. Ideally, I want to define a 4-bit, or 8-bit macro that represents true and false, and will evaluate as such in an if-statement.
Edit:
When I define a macro
#define True 0
#define False !True
and then print the size, it returns a size of 4 bytes, which is very inefficient.
Edit2:
I just read up on bitpacking, and however little bits I could have for a boolean would be best. I'm just not too sure how to bitpack a struck that has the size of a few bits.
Edit3:
#include <stdio.h>
#include <string.h>
#define false (unsigned char(0))
#define true (!false)
int main() {
if (true) {
printf("The size of true is %d\n", sizeof(true));
}
}
gives the following output
test.c: In function ‘main’:
test.c:8:9: error: expected ‘)’ before numeric constant
test.c:9:51: error: expected ‘)’ before numeric constant
Try this instead for your macros:
#define false ((unsigned char) 0)
#define true (!false)
This won't fix your space needs though. For more efficient storage, you need to use bits:
void SetBoolValue(int bitOffset, unsigned char *array, bool value)
{
int index = bitOffset >> 3;
int mask = 1 << (bitOffset & 0x07);
if (value)
array[index] |= mask;
else
array[index] &= ~mask;
}
bool GetBoolValue(int bitOffset, unsigned char *array)
{
int index = bitOffset >> 3;
int mask = 1 << (bitOffset & 0x07);
return array[index] & mask;
}
Where each value of "array" can hold 8 bools. On modern systems, it can be faster to use a U32 or U64 as the array, but it can take up more space for smaller amounts of data.
To pack larger amounts of data:
void SetMultipleBoolValues(int bitOffset, unsigned char *array, int value, int numBitsInValue)
{
for(int i=0; i<numBitsInValue; i++)
{
SetBoolValue(bitOffset + i, array, (value & (1 << i)));
}
}
And here would be a driver:
int main(void)
{
static char array[32]; // Static so it starts 0'd.
int value = 1234; // An 11-bit value to pack
for(int i=0; i<4; i++)
SetMultipleBoolValues(i * 11, array, value, 11); // 11 = 11-bits of data - do it 4 times
for(int i=0; i<32; i++)
printf("%c", array[i]);
return 0;
}
If you are using this in a structure, then you will want to use a bit field.
struct {
unsigned flag : 1;
/* other fields */
};
If you are wanting an array of boolean values, you should implement a bit vector (I was about to implement one, but Michael Dorgan's already done it).
First of all, there's no storage associated with your macros; they expand to the integer constants 0 and 1. The sizeof evaluates to 4 because the expressions have integer type. You can certainly assign those values to objects of smaller type (short or char).
For me, life got a lot simpler when I stopped using TRUE and FALSE macros1. Remember that in C, a zero-valued integral expression evaluates to false, and all non-zero-valued integral expressions evaluate to true.
If you want to store values into something smaller than 8 bits, then you're going to have to do your own bit packing, something like
#define TEST(x,bit) ((x) & (1 << (bit)))
#define SET(x,bit) ((x) |= (1 << (bit)))
#define CLEAR(x,bit) ((x) &= ~(1 << (bit)))
The smallest useful type for this is unsigned char. So if you need to store N single-bit values, you need an array of N/CHAR_BIT+1 elements. For example, to store 10 single-bit boolean values, you need 2 eight-bit array elements. Bits 0 through 7 will be stored in element 0, and bits 8 through 10 will be stored in element 1.
So, something like
#define MAX_BITS 24
unsigned char bits[MAX_BITS / CHAR_BIT + 1];
int bit = ...;
SET(bits[bit/CHAR_BIT], bit % CHAR_BIT);
if ( TEST(bits[bit/CHAR_BIT], bit % CHAR_BIT) )
{
// do something if bit is set
}
CLEAR(bits[bit/CHAR_BIT], bit % CHAR_BIT);
No warranties express or implied; I don't do a lot of bit twiddling. But hopefully this at least points you in the right direction.
1. The precipitating event was someone dropping a header where TRUE == FALSE. Not the most productive afternoon.
You should probably just use an unsigned char, it will be the smallest individually addressable type:
typedef unsigned char smallBool;
smallBool boolMatrix[M][N];
The above will use M * N bytes for the matrix.
Of course, wasting CHAR_BIT - 1 bits to store a single bit is ... wasteful. Consider bit-packing the boolean values.

Resources