Skip to main content
Code Review

Return to Question

deleted 105 characters in body
Source Link
Madagascar
  • 10.2k
  • 1
  • 15
  • 51

The requirement is to define a macro which takes a single argument with the following contraints:that is a string literal.

  • Is a character pointer
  • Must be non-null
  • Must be immutable
  • Must be 0-terminated

The requirement is to define a macro which takes a single argument with the following contraints:

  • Is a character pointer
  • Must be non-null
  • Must be immutable
  • Must be 0-terminated

The requirement is to define a macro which takes a single argument that is a string literal.

added 70 characters in body
Source Link
Madagascar
  • 10.2k
  • 1
  • 15
  • 51

Note: I am looking for a solution that would work with at least C99.

Note: I am looking for a solution that would work with at least C99.

Source Link
Madagascar
  • 10.2k
  • 1
  • 15
  • 51

C - Force a macro argument to be a string literal

The requirement is to define a macro which takes a single argument with the following contraints:

  • Is a character pointer
  • Must be non-null
  • Must be immutable
  • Must be 0-terminated

My first try at it was to surround it with empty string literals (I got this from Modern C):

#define SV(str) (sizeof("" str "") - 1)

Now if I do:

int main(void)
{
 static const char *const s = "hello";
 char word[] = "hello";
 double a = 0.0f;
 double *d = &a;
 printf("%zu\n", SV(NULL));
 printf("%zu\n", SV(word));
 printf("%zu\n", SV(d));
 printf("%zu\n", SV(s));
 return 0;
}

It fails to compile, which was the expected behavior:

macro_str.c: In function ‘main’:
macro_str.c:4:33: error: called object is not a function or function pointer
 4 | #define SV(str) (sizeof("" str "") - 1)
 | ^~
macro_str.c:19:21: note: in expansion of macro ‘SV’
 19 | printf("%zu\n", SV(NULL));
 | ^~
macro_str.c:4:40: error: expected ‘)’ before string constant
 4 | #define SV(str) (sizeof("" str "") - 1)
 | ~ ^~
macro_str.c:19:21: note: in expansion of macro ‘SV’
 19 | printf("%zu\n", SV(NULL));
 | ^~
macro_str.c:20:24: error: expected ‘)’ before ‘word’
 20 | printf("%zu\n", SV(word));
 | ^~~~
macro_str.c:4:36: note: in definition of macro ‘SV’
 4 | #define SV(str) (sizeof("" str "") - 1)
 | ^~~
macro_str.c:4:32: note: to match this ‘(’
 4 | #define SV(str) (sizeof("" str "") - 1)
 | ^
macro_str.c:20:21: note: in expansion of macro ‘SV’
 20 | printf("%zu\n", SV(word));
 | ^~
macro_str.c:21:24: error: expected ‘)’ before ‘d’
 21 | printf("%zu\n", SV(d));
 | ^
macro_str.c:4:36: note: in definition of macro ‘SV’
 4 | #define SV(str) (sizeof("" str "") - 1)
 | ^~~
macro_str.c:4:32: note: to match this ‘(’
 4 | #define SV(str) (sizeof("" str "") - 1)
 | ^
macro_str.c:21:21: note: in expansion of macro ‘SV’
 21 | printf("%zu\n", SV(d));
 | ^~
macro_str.c:22:24: error: expected ‘)’ before ‘s’
 22 | printf("%zu\n", SV(s));
 | ^
macro_str.c:4:36: note: in definition of macro ‘SV’
 4 | #define SV(str) (sizeof("" str "") - 1)
 | ^~~
macro_str.c:4:32: note: to match this ‘(’
 4 | #define SV(str) (sizeof("" str "") - 1)
 | ^
macro_str.c:22:21: note: in expansion of macro ‘SV’
 22 | printf("%zu\n", SV(s));
 | ^~
make: *** [<builtin>: macro_str] Error 1

Then I proceeded to ask a question on StackOverflow and found instances where this would fail:

SV()
SV(/*comment*/)
SV(-)
SV("abc" - "def")

So I added some more expressions , suggested by @n. m. could be an AI, to it:

#define SV(str) ("" str "", (str)[0], sizeof(str) - 1)

Now it fails for these 4 edge-cases as well. Yet there are still things like:

// I believe the second one is defined-behavior. 
SV("abcd" - sizeof "e"); 
SV("abcd" + sizeof "e"); 

for which it would compile cleanly. Whilst I am satisfied with the final macro and it serves my use-case, I believe there might still be some improvements it could use.

How can it be made more robust?

lang-c

AltStyle によって変換されたページ (->オリジナル) /