2

Consider the following functions:

void consumer(unsigned char byte);

void dispatcher(unsigned char *bytes, size_t size){
    while(size--) {
        consumer(*(bytes++));
    }
}

void full_wrapper(char *string, size_t len){
    dispatcher((unsigned char *)string, len);
}
void auto_wrapper(char *string){
    full_wrapper(string, strlen(string));
}

Now consider the following variables:

char a[] = "abcd";
char b[20] = {'a', 'b', 'c', 'd'};
char *c = "abcd";
char *d = malloc(5 * sizeof(char));

I want to use full_wrapper only for char arrays like a by writing:

full_wrapper(a, (sizeof(a) / sizeof(char)) - 1);

And I want to use auto_wrapper for all other kinds by writing:

auto_wrapper(b);
auto_wrapper(c);
auto_wrapper(d);

In order to do so, I created the following macro, by using some built-in functions provided by GCC:

#define WRAPPER(x) __builtin_types_compatible_p(typeof(x), char[]) ? full_wrapper(x, (sizeof(x) / sizeof(char)) - 1) : auto_wrapper(x)

This macro is capable of working fine in following cases:

WRAPPER(a);//uses full_wrapper, as intended
WRAPPER(c);//uses auto_wrapper, as intended
WRAPPER(d);//uses auto_wrapper, as intended

But the macro is not able to distinguish between a and b in the following case:

WRAPPER(b);//uses full_wrapper, not good

So I was wondering if there is a way (using GCC and maybe some other non-portable methods), to distinguish char arrays which are assigned from strings literals from all other char arrays, specifically in an embedded environment where there is no OS?

Please note that this question is not similar to How to distinguish between strings in heap or literals?


Edit:

Please note that the functions consumer and dispatcher, (unlike the functions full_wrapper and auto_wrapper, that I wrote my self,) are just some examples and the real functions, are from a library which I do not have access to it source code.

Also for the function consumer and dispatcher, it is important, not to work on '\0' (NULL terminating) characters.

My purpose of writing those wrapper functions is to have a universal function/macro to to use in order to call dispatcher and possibly reducing the (possible) overheads (,if any) for calling strlen for c-strings which their size in known at compile time.

So for example the following macro could (some what but not exactly) answer my question:

#define WRAPPER(x) __builtin_types_compatible_p(typeof(x), char[]) ? strlen(x) == (sizeof(x) / sizeof(char) -1) ? full_wrapper(x, (sizeof(x) / sizeof(char)) - 1) : auto_wrapper(x) : auto_wrapper(x)

But it does not solve my problem.

I know the types a and b are both char arrays of fixed lengths (at the compile time. And none of them is a VLA). But I am hopping to find a method which can distinguish between the ones which are initialized from an string literals and those which are not initialized from string literals.

AKL
  • 1,367
  • 7
  • 20
  • What would you want `char e[5] = {'a', 'b', 'c', 'd'};` to use? It is the same value as `a`. – chux - Reinstate Monica Aug 13 '22 at 18:32
  • @chux-ReinstateMonica , thank you for your comments, I have corrected my previous mistakes in the code accordingly and I also have added an edit section to clarify my situation and my purpose. Please have a look – AKL Aug 13 '22 at 19:44
  • You can find out if something is pointing at a string literal at run-time by ensuring that you know what addresses they are allocated at and then checking if a pointer points into that segment. – Lundin Aug 13 '22 at 20:17
  • 2
    Your goal for all this seems to stem from "and possibly reducing the (possible) overheads (,if any) for calling strlen for c-strings which their size in known at compile time.". I very much doubt code will realize any significant time savings by foregoing `strlen()`. Note that a good compiler may optimize out the `strlen()` and replace it with a constant - negating all this effort. – chux - Reinstate Monica Aug 13 '22 at 23:14

0 Answers0