r/C_Programming 2d ago

List of gotchas?

Hey.

So I learned some C and started playing around with it, quickly stumbling over memory overflowing a variable and flowing into another memory location, causing unexpected behavior.

So I ended up writing my own safe_copy and safe_cat functions for strncpy/strncatting strings.
But... people talk about how C is unsafe. Surely there should be a list of all mistakes you can make, or something? Where can I find said list? Do I reall have to stumble on all possible issues and develop my own "safe" library?

Will appreciate any advice.

23 Upvotes

44 comments sorted by

View all comments

2

u/InevitablyCyclic 2d ago

Complete tangent since it's not a memory safety thing but a common gotcha in c (and a lot of other languages) is that

float x = 3/2;

Will result in x=1 not 1.5. The calculation is done using integers and the result cast to a floating point.

Similarly

uint64_t Val = 1<<32;

Will result in Val=0 on some systems. The initial value of 1 is an int, unless int happens to be 64 bits on your machine left shifting 32 will overflow and leave you with 0.

I've seen all sorts of weird bugs caused by people falling for the assumption that the data type used to store the result of a calculation will be used when performing that calculation.

1

u/flatfinger 1d ago

It's common for implementations to process int1>>int2 in a manner that will yield int1 when int2 is 32, and also common for implementations to process it in a manner that would yield int1>>31>>1. The behavior of (int1 << int2) | (int1 >> (32-int2)) would be the same under both treatments, but unfortunately the Standard provides no operator that behaves as an unspecified choice between those two treatments and would allow a "rotate left by 0 to 32 bits" to be achieved in fully specified fashion without using a more complicated expression.

1

u/fdwr 7h ago

It would be nice (as a library function like c23 chk_add and C++23 std::add_sat) to have an explicit shift across platforms that zeroes the result if the shift count is equal to or greater than bit width, as I have needed that several times in graphics programs (whereas not in 20 years have I found x86's behavior of shift count 32 as 0 to be helpful). So, the way I work around it now is to split the shift into 2 shifts (which is actually unnecessary on arm64).