print the name of macro identifier associated with integer with variable - c

I cannot find something similar to this.
#define ONE 1
#define TWO 2
int main()
{
int x = ONE;
printf("%s \n", x);
}
//the desirable output will be "ONE"
Now, I saw the other answers with the
#define PRINT(X) printf("%s \n", #x);
and I did not find how to use it to get what I want.

There is no direct way to do this. The only information you have in your printf call is a variable x whose current value happens to be 1 (at run time), which happens to be the expansion of a macro whose name is ONE. There is no way for the compiler to figure out the name ONE from that information. There might be several different macros with the same definition, or there might not be any.
If you want to print the string ONE given the integer value 1, you're going to have to set up some kind of lookup table or function. For example:
const char *const names[] = { "ZERO", "ONE", "TWO", "THREE", "FOUR", /* etc. */ };
printf("%s\n", names[x]);
It would be entirely up to you to get the names right, so that for example 1 doesn't map to "THREE".

As #KeithThompson said, there is no easy way.
But there is a clever hack which does more or less what you ask for.
#define MY_ENUM_LIST \
X( ONE , 1 ) \
X( TWO , 2 ) \
X( THREE , 3 )
#define X(name, value) name = value,
enum MyEnum {MY_ENUM_LIST};
#undef X
const char *my_enum_to_str(enum MyEnum e)
{
switch (e)
{
#define X(name, value) case value: return #name;
MY_ENUM_LIST
#undef X
default:
return "<invalid>";
}
}
int main()
{
int x = ONE;
printf("%d\n", x); // prints "1"
printf("%s\n", my_enum_to_str(x)); // prints "ONE"
return 0;
}
It has following advantages over the naïve lookup table:
No need to repeat enumerator names twice.
You can have any enumerator values, not only a contiguous range.
You can't accidentaly assign an incorrect name to an enumerator.

Related

Overload function in C language using _Generic mix function call with constants returning

I see there are two ways of writing a _Generic statement:
A.
#define len(x) _Generic((x), char*:f1, int: f2, char: f3, double:f4) (x)
I want to underline the (x).
B.
#define len(x) _Generic((x), char*:f1(x), int: f2(x), char: f3(x), double:f4)
The problem is that in the B case, I got errors:
expected char* but argument is of type int
incompatible type for argument 1 of f...
How Am I suppose to write this overload if I want to mix functions with constants?
I'm trying to get:
1 if the argument is of type char;
the length of the string if the argument is of type char *;
the number of decimal digits (possibly increased by one when the argument is negative) if the argument is of type int;
the length of the string produced by the printf() function using the %f specifier if the argument is of type double.
int_len(int number)
{
unsigned counter=0;
if(number < 0)
{
counter++;
}
while(number)
{
counter++;
number /= 10;
}
return counter;
}
int char_len(int param)
{
return 1;
}
int double_len(double param)
{
return 10;
}
int charptr_len(char* ptr)
{
unsigned count=0;
while(*ptr)
{
ptr++;
count++;
}
return count;
}
#define len(x) _Generic((x), char*:charptr_len(x), int: int_len(x), char:1, double:double_len(x))
int main(void) {
printf("%d\n",len(261321));
printf("%d\n",len(261.321));
printf("%d\n",len((char)'x'));
printf("%d\n",len("A kingdom for a horse!"));
return 0;
}
p.s I know the code might be stupid but I just wanted it to work .
I'm trying to get:
Imagine the compiler takes all paths for any input. Whichever path compiler takes, they all have to be "valid" for any input, even if only one expression is used and evaluated and the rest is discarded, they technically have to be "valid".
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#define len(x) _Generic((x), \
char: 1, \
char *: (int)strlen((char*)(void*)(uintptr_t)x), \
int: snprintf(NULL, 0, "%d", x), \
double: snprintf(NULL, 0, "%f", x))
int main() {
printf("%d\n",len(261321));
printf("%d\n",len(261.321));
printf("%d\n",len((char)'x'));
printf("%d\n",len("A kingdom for a horse!"));
}
Godbolt link. I ended up with the super casts in strlen to handle strlen(261.321) case - to cast a double to a pointer so that compiler doesn't complain. It doesn't matter in "abc" case where I hope that the cast do not modify the pointers value. That's why it's easier to develop separate functions for each case. You may also (ab-)use variadic function arguments in generics to easily remove any casts and deal with them inside your functions with va_args.
(Little self promotion: I recently explored limits of _Generic by developing type-safe-ish printf, with that library it would be just #define len(x) ysprint(NULL, 0, x), but I already see that the number of digits after comma in double case is different from %f in printf).

how do I assign a value to a word for easy use when referencing the value of said word?

I am currently trying to make a small game in the c programing language for a portfolio. I am new to c so I don't know all of the ticks. Currently, I am trying to assign values to enum's though I don't know if that is correct.
// C program for generating a
// random number in a given range.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "Test.h"
enum mods{
Cha, Str, Dex, Con, Int, Wis // <-this line is the only line that is my code (of this document I have more that will reference this document) the rest I learned from others
};
// Generates and prints 'count' random
// numbers in range [lower, upper].
void printRandoms(int lower, int upper,
int count)
{
int i;
for (i = 0; i < count; i++) {
int num = (rand() %
(upper - lower + 1)) + lower;
printf("%d ", num);
}
}
// Driver code
int main(enum mods Str)
{
int lower = 6, upper = 18, count = 1;
// Use current time as
// seed for random generator
srand(time(0));
printRandoms(lower, upper, count);
printf("My enum Value : %d\n", (int)Str);
return 0;
*edit Sorry for the confusion. I want to be able to reference this product of this line of code over and over again in the main sheet/program. I want it to be a random start so it isn't the same game every time. How do I do that? (for an example of the end product:
if (Str >= 10)
printf("pass skill check to lift the log\n");
else
printf("you drop the log on your foot and take 1d4 damage\n");
enum (health -1d4[will make actual code for this but not yet])
what I need answered
how to make each of the enum mods = a random number at the start of the program to be referenced in the main program
)
If I understood you correctly, you want the mod values to be randomly generated.
Use the enum values as array indices into an array big enough to hold all your mod attributes. Like this, for example:
enum mods = { Cha, Str, Dex, Con, Int, Wis, Mod_Max };
int mod_values[Mod_Max];
Keeping Mod_Max (or whatever you'd like to call it) as the last element of the enum, this will give you simple way to refer to the size of the array. Populating the array with values:
for (int i = 0; i < Mod_Max; i++) {
mod_values[i] = ...;
}
And getting a value of a given "mod" would simply be (for example Str):
mod_values[Str];
EDIT: This way, lets you further modify the mod values down the line, rather than having them as constants
I believe you're asking how to have values for each element in your enum. Well all you have to do is simply assign said value-
enum mods { foo = 77, bar = 42, baz = 3 };
Then you can access said values like so-
enum mods mod_enum = foo;
printf("%d", mod_enum);
The above will print 77
You can also directly use the value of one of the elements from said enum
printf("%d\n", bar);
The above prints 42
Read more about enums

Can a C program determine a macro identifier/enum name based on its value?

Let's say we define some error codes as macros -
#define ERR_SUCCESS 0
#define ERR_BAD_INPUT 1
...
or as an enumerated data type -
enum err_t = { ERR_SUCCESS, ERR_BAD_INPUT, ...};
and one of these ids is returned by a function such as -
int foo(); /* if foo() returns 0, it means success, etc */
Can the caller of foo() determine which identifier / name (ERR_SUCCESS, ERR_BAD_INPUT, ...) is linked to the int return value?
No.
Processor macros, as the name suggested, are resolved while preprocessing before the compilation step starts. While calling, i.e. during run time, there is no reference to the names like ERR_SUCCESS, ERR_BAD_INPUT etc. and that's why you can't determine the identifier name at run time.
Simliar reasoning goes for enum too since enum creates compile time constants and you can't get the identifier name during run time.
Not directly, as pointed out by others those identifiers are not available at runtime, but you can use a parallel list of names (an X Macro can help):
#include <stdio.h>
#define ERRS \
X(ERR_SUCCESS) \
X(ERR_BAD_INPUT) \
X(ERR_MORE)
#define X(x) x,
enum err_t {ERRS};
#undef X
#define X(x) #x,
static char *err_name[] = {ERRS};
#undef X
static int foo(void)
{
/* ... */
return ERR_BAD_INPUT;
}
int main(void)
{
printf("%s\n", err_name[foo()]);
return 0;
}
Output:
ERR_BAD_INPUT
Since C99, Keine Lust's macros could even be extended to set values explicitly:
#define X(x) x,
#define X_WITH_VALUE(x, v) x = v,
and:
#define X(x) [x] = #x,
#define X_WITH_VALUE(x, v) X(x)
finally a function:
char const* getName(enum E e)
{
char const* n = e < sizeof(arr)/sizeof(*arr) ? arr[e] : NULL;
return n ? n : "<unknown error>";
}
Edit (in response to comment): Assigning values explicitly allows to introduce
(desired!) gaps and synonyms:
enum Flags
{
None = 0,
F0 = 1,
F1 = 2,
F2 = 4,
F3 = 8,
G3 = F3,
}
This will result in gaps in the array, though, resulting in necessity for the null pointer check in the function. If your enum values get large, the array might get huge, so the array solution might not be suitable any more...
The synonyms impose another problem, see Jens's answer. The problem is solved partially, code does work, but you do not necessarily get back the synonym originally used, but always the last defined one instead! In above example, this would be G3 even if you used F3 in your code. So you have to define the desired synonym last (which seems a little unnatural to me...) or you use the SYNONYM macro below.
Some special cases with array size might be solved with additional tricks, e. g. if you have subsequent values with a higher start value:
#define X(x) [x - Initial] = #x,
char const* n = e < sizeof(arr)/sizeof(*arr) ? arr[e - Initial] : NULL;
Interesting gets the powers of two enum above:
#define X(x, p) x = (1 << p),
enum err_t {None = 0, ERRS};
char const* getName(enum E e)
{
if(e == None)
return S(None); // stringification macro, yet to be defined
// check, if power of two:
if((unsigned int) e & ((unsigned int) e - 1))
{
int index = log2(e);
if(index < sizeof(arr)/sizeof(*arr)
return arr[index];
}
return "<unknown>";
}
The power of two check is coming from Sean Eron Anderson (here exactly), you find nice solutions to calculate log2 there, too, e. g. this one.
Completely different approach, suitable for any kind of distinct values (but synonyms need to be handled explicitly!):
#define X(x) x,
#define X_WITH_VALUE(x, v) x = v,
#define SYNONYM(y, x) y = x,
#define X(x) case x: return #x;
#define X_WITH_VALUE(x, v) X(x)
#define SYNONYM(y, x)
char const* getName(enum E e)
{
switch(e)
{
ERRS
default:
return "<unknown>";
}
}
No. This is easy to see when you realize the mapping from values to names is not bijective. Which is a fancy way to say that macros such as
#define ZERO 0
#define ZILCH 0
#define NADA 0
#define NIENTE 0
are allowed to coexist. Given 0, which is the associated name?
The same argument applies to enum identifiers.
No, it's not supported by the compiler. The compiler gets the output of the C preprocessor with the #defines replaced by there values. You need to detect the values in your code. e.g. like in this question.

Check either its a char or an integer

this is an integer array:
int values[] = { 75, '*', 5,'-' };
for(i=0 ; i<size ; i++){
// Here
}
how to check if the values[i] is an integer or an operation ??
maybe the value equals the Ascii of an operation,, how to deal with it in this case??
You can't. As for as the compiler is concerned, the constants 42 an '*' are one and the same. In the compiled object code, they're both represented as the integer 42.
If you need to differentiate between integers and characters, either use a boolean flag or enum indicating the type of the value, or keep your integers and characters in separate arrays.
Note that in C++, but not in C, there is a slight difference: 42 has the type int, whereas '*' has the type char, so you can differentiate this fact using overloaded functions or templates.
That's a dangerous road to go down. The array in your example will translate (during compilation) into:
int values[] = {75, 42, 5, 45};
So when you see the number 42... what is it? Is it the '*' character, or did you actually mean the number 42?
You can't rely on typecasting, either, because all your values will be cast to ints, since they're stored in an integer array. Your best bet is to make a struct that holds both type and value, like so:
typedef struct
{
int type; //0 for int, 1 for operator, and so forth.
int value; //holds either a character code or an integer value
//you could use a union here, if you felt it would make things cleaner...
} Token;
Then checking to see what type a token is is simply a matter of looking at token.type.
Hope this helps!
PS: The cheating answer would be to use a dynamically typed language. Lots less work on your part, but slower, and I don't know if it's an option for you.
Your array elements cannot be simple integers.
Try this instead:
enum ElementType {INTEGER, OPERATION};
struct ArrayElement {
enum ElementType etype;
int evalue;
};
struct ArrayElement values[] = {
{INTEGER, 75}, {OPERATION, '*'}, {INTEGER, 5}, {OPERATION, '-'}
};
for (i = 0; i < sizeof values / sizeof *values; i++) {
/* Here */
switch (values[i].etype) {
default: printf("unrecognized type. value is %d.\n", values[i].value);
break;
case INTEGER: printf("INTEGER with value %d.\n", values[i].value);
break;
case OPERATION: printf("OPERATION with value '%c'.\n", values[i].value);
break;
}
}

Number of elements in an enum

In C, is there a nice way to track the number of elements in an enum? I've seen
enum blah {
FIRST,
SECOND,
THIRD,
LAST
};
But this only works if the items are sequential and start at zero.
If you don't assign your enums you can do somethings like this:
enum MyType {
Type1,
Type2,
Type3,
NumberOfTypes
}
NumberOfTypes will evaluate to 3 which is the number of real types.
I don't believe there is. But what would you do with such a number if they are not sequential, and you don't already have a list of them somewhere? And if they are sequential but start at a different number, you could always do:
enum blah {
FIRST = 128,
SECOND,
THIRD,
END
};
const int blah_count = END - FIRST;
Old question, I know. This is for the googlers with the same question.
You could use X-Macros
Example:
//The values are defined via a map which calls a given macro which is defined later
#define ENUM_MAP(X) \
X(VALA, 0) \
X(VALB, 10) \
X(VALC, 20)
//Using the map for the enum decl
#define X(n, v) [n] = v,
typedef enum val_list {
ENUM_MAP(X) //results in [VALA] = 0, etc...
} val_list;
#undef X
//For the count of values
#define X(n, v) + 1
int val_list_count = 0 + ENUM_MAP(X); //evaluates to 0 + 1 + 1 + 1
#undef X
This is also transparent to an IDE, so auto-completes will work fine (as its all done in the pre-processor).
Unfortunately, no. There is not.
I know this is a very old question, but as the accepted answer is wrong, I feel compelled to post my own. I'll reuse the accepted answer's example, slightly modified.
(Making the assumption that enums are sequential.)
// Incorrect code, do not use!
enum blah {
FIRST = 0,
SECOND, // 1
THIRD, // 2
END // 3
};
const int blah_count = END - FIRST;
// And this above would be 3 - 0 = 3, although there actually are 4 items.
Any developer knows the reason: count = last - first + 1.
And this works with any combination of signs (both ends negative, both positive, or only first end negative). You can try.
// Now, the correct version.
enum blah {
FIRST = 0,
SECOND, // 1
THIRD, // 2
END // 3
};
const int blah_count = END - FIRST + 1; // 4
Edit: reading the text again, I got a doubt. Is that END meant not to be part of the offered items? That looks weird to me, but well, I guess it could make sense...
Well, since enums can't change at run-time, the best thing you can do is:
enum blah {
FIRST = 7,
SECOND = 15,
THIRD = 9,
LAST = 12
};
#define blahcount 4 /* counted manually, keep these in sync */
But I find it difficult to envisage a situation where that information would come in handy. What exactly are you trying to do?
int enaumVals[] =
{
FIRST,
SECOND,
THIRD,
LAST
};
#define NUM_ENUMS sizeof(enaumVals) / sizeof ( int );
#include <stdio.h>
// M_CONC and M_CONC_ come from https://stackoverflow.com/a/14804003/7067195
#define M_CONC(A, B) M_CONC_(A, B)
#define M_CONC_(A, B) A##B
#define enum_count_suffix _count
#define count(tag) M_CONC(tag, enum_count_suffix)
#define countable_enum(tag, ...) \
enum tag {__VA_ARGS__}; \
const size_t count(tag) = sizeof((int []) {__VA_ARGS__}) / sizeof(int)
// The following declares an enum with tag `color` and 3 constants: `red`,
// `green`, and `blue`.
countable_enum(color, red, green, blue);
int main(int argc, char **argv) {
// The following prints 3, as expected.
printf("number of elements in enum: %d\n", count(color));
}

Resources