Currently, I have the following block of code to make safe string copying (it works):
#define STRCPY(dst, src) do { assert(((void*)(dst)) == ((void*) & (dst))); \
                              strlcpy(dst, src, sizeof(dst)); } while (0)
So it accepts the construction like:
const char *src = "hello";
char dest[5];
STRCPY(dest, src); //hell
And denies the following:
void (char *dst) {
    STRCPY(dst, "heaven"); //unknown size of dst
}
The problem is that the block of code creates an assertion. Is there a way to perform this check on compilation time?
So I want to have the error on compilation (like creating an array with negative size) instead of crashing code if it possible.
If standard C is available, then you can do this:
#define STRCPY(dst, src)                                        \
  _Generic(&(dst),                                              \
           char(*)[sizeof(dst)]: strlcpy(dst,src,sizeof(dst)) )
Explanation:
You can't use a _Generic expression on an array type, because it is not one of the special cases that is exempt from the "array decay" rule (C17 6.3.2.1 §3). So by simply using _Generic((dst), ... in my example, dst would end up as a char* when the expression is evaluated, and then we would lose the information of its original type.
But if we take the address of the array using &, we do utilize one of those special cases and the array decay doesn't happen. Instead we end up with an array pointer, meaning that _Generic will have to check for an array pointer of the expected type and size: char(*)[sizeof(dst)].
As a side-note/safety concern, I never use do-while(0) macros and discourage them, but that's another story.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With