Is it possible to determine if an argument passed in macro or function is a string literal at compile time or run time?
For example,
#define is_string_literal(X)
...
...
is_string_literal("hello") == true;
const char * p = "hello";
is_string_literal(p) == false;
or
bool is_string_literal(const char * s);
is_string_literal("hello") == true;
const char * p = "hello";
is_string_literal(p) == false;
Thanks.
A "string literal" is a sequence of characters from the source character set enclosed in double quotation marks (" "). String literals are used to represent a sequence of characters which, taken together, form a null-terminated string. You must always prefix wide-string literals with the letter L.
A String literal is a String object, but a String object is not necessarily a String literal. And once assigned to a reference variable, it's all but impossible to tell if a given String object is a literal or not. This was marked as a duplicate of something it doesn't duplicate at all.
A string literal is a sequence of zero or more characters enclosed within single quotation marks. The following are examples of string literals: 'Hello, world!' 'He said, "Take it or leave it."'
YES! (Thanks to James McNellis and GMan for corrections. Updated to correctly handle concatenated literals like "Hello, " "World!"
which get stringized before concatenation.)
#define is_literal_(x) is_literal_f(#x, sizeof(#x) - 1)
#define is_literal(x) is_literal_(x)
bool is_literal_f(const char *s, size_t l)
{
const char *e = s + l;
if(s[0] == 'L') s++;
if(s[0] != '"') return false;
for(; s != e; s = strchr(s + 1, '"'))
{
if(s == NULL) return false;
s++;
while(isspace(*s)) s++;
if(*s != '"') return false;
}
return true;
}
This will stringify the argument before passing it to the function, so if the argument was a string literal, the argument passed to our function will be surrounded with quote characters.
If you consider this a string literal:
const char *p = "string";
// should is_literal(p) be true or false?
I cannot help you. You might be able to use some implementation-defined (or *shudder* undefined) behavior to test whether or not a string is stored in read-only memory, but on some (probably older) systems p
could be modified.
For those who question the use of such a function, consider:
enum string_type { LITERAL, ARRAY, POINTER };
void string_func(/*const? */char *c, enum string_type t);
Rather than explicitly specifying the second argument to string_function
on every call, is_literal
allows us to wrap it with a macro:
#define string_func(s) \
(string_func)(s, is_literal(s) ? LITERAL :
(void *)s == (void *)&s ? ARRAY : POINTER)
I can't imagine why it would make a difference, except in plain C where literals aren't const
and for some reason you don't want to/can't write the function as taking a const char *
instead of a char
. But there are all kinds of reasons to want to do something. Someday you, too may feel the need to resort to a horrible hack.
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