String literals are one place where the compiler implements the null-termination, so it is built-in in that sense.
As per the OP’s example, a wrapper macro like their STR can work around this.
I don't have an issue with the OP's example, which is quite nifty indeed, despite the penalties incurred.
That's incorrect. If I write this in my .c file:
char *s = "Hi";
The compiler will not treat that as a simple mere pointer to char when allocating space for it in the binary. It will see that the rhs is surrounded by double quote characters, and allocate 3 bytes for it, instead of 2, and put a NUL byte after the bytes for 'H' and 'i'.Nul-tetminated strings are absolutely a part of the language. Certainly you can make and store strings in a different way if you'd like, but the language itself defines what a string and string literal is.
s is still a pointer to character.
This is just an optimised shorthand for (assuming ASCII):
char s[3];
Which is then initialised with: 0x48,0x69,0x00
There simply is no such thing as a string type in C.
All the "string" functions work on a char pointer which is incremented until it points to a 0.
Once you go down the route proposed by many of the comments here - why not enhance it to deal with UTF8... Or rather implement a proper "array" type? What about the lack of multidimensional arrays instead of the pointer to pointer to ... approach? Idiosyncracies such as "int a[2][3];" being of type "int *" and not "int **"?
C was never intended to shield you from mistakes, but rather replace a macro assembler. ANSI C addressed some of the issues in the original K&R C, but that is about it.
If your use case would benefit from all of these protections, there are plenty of higher level language alternatives...