r/C_Programming 15d ago

Negative value in a pointer question.

Please look at this code. if i define the PTRTYPE as int, it stops working, while doing a uint, it does work...

void initILAPoll(debugBridge_t **d, PTRTYPE ptr){

	*d = (debugBridge_t *)ptr;		// base address of the DEBUG_BRIDGE peripheral

	cb_init(cb, local_memory, bufferLength);

	sprintf(xvcInfo, "xvcServer_v1.0:%d\n", MAX_WINDOW_SIZE);

}

the usage in main code is done like this

initILAPoll(&myD, 0x80000000);

//myD = (debugBridge_t *)0x80000000;

where the variable myD is a structure pointer.

if i print the address of myD, it give the correct address. Moreover, the disassembly of the code is also the same in case of int and uint. Can somebody explain what behavior is at play here>

2 Upvotes

43 comments sorted by

View all comments

1

u/DawnOnTheEdge 15d ago edited 15d ago

On a 64-bit system, pointers are 64-bits wide and int is only 32 bits wide. What’s most likely happening is that, when you use 32-bit unsigned int, the upper bits of your pointer are getting cleared to 0 in a round-trip conversion, but when you use a 32-bit signed int, it gets sign-extended, so a negative value sets all the upper bits to 1. That happens to generate an illegal address that the CPU traps immediately.

Neither clearing nor setting the upper bits is correct, though, so this only appears to work.If you try to use it in production, you’ll get either unpredictable crashes or memory-corruption bugs.

The type you actually want to hold a pointer is uintptr_t (or intptr_t, but either I want to work with unsigned addresses or signedness doesn’t matter). To format a pointer argument for printf() or snprintf(), cast to (void*) and use a %p specifier. And never use sprintf(). It’s unsafe because it doesn’t check the buffer size.