Reputation: 2194
Recently I learned about _Generic
. In my attempt to use it as a generic length-macro I stumbled upon a weird issue. While LENA(x)
works perfectly fine, the generic LEN(x)
fails to compile unless I remove the default
one.
#include <stdio.h>
#include <string.h>
#define LENA(x) sizeof(x)/sizeof((x)[0])
#define LEN(x) _Generic((x), \
int : snprintf(NULL, 0, "%d" , (x)), \
unsigned int : snprintf(NULL, 0, "%u" , (x)), \
long : snprintf(NULL, 0, "%ld" , (x)), \
unsigned long : snprintf(NULL, 0, "%lu" , (x)), \
long long : snprintf(NULL, 0, "%lld", (x)), \
unsigned long long : snprintf(NULL, 0, "%llu", (x)), \
float : snprintf(NULL, 0, "%f" , (x)), \
double : snprintf(NULL, 0, "%f" , (x)), \
long double : snprintf(NULL, 0, "%Lf" , (x)), \
default : sizeof((x))/sizeof((x)[0]) \
)
int main() {
int i = 12345;
unsigned long ul = 18446744073709551615UL;
double d = 3.14159;
char str[] = "Hello, World!";
int arr[] = {1, 2, 3, 4, 5, 6, 7};
printf("Length of int : %d\n", LEN(i)); // Output: 5
printf("Length of Ulong: %d\n", LEN(ul)); // Output: 20
printf("Length of array: %d\n", LENA(arr)); // Output: 7
//printf("Length of array: %d\n", LEN(arr));
//printf("Length of str: %d\n", LEN(str));
return 0;
}
(specifically the /sizeof((x)[0]
-part of it).
ERROR!
/tmp/21gk5WXdQu.c: In function 'main':
/tmp/21gk5WXdQu.c:15:46: error: subscripted value is neither array nor pointer nor vector
15 | default : sizeof(x)/sizeof((x)[0]) \
| ^
/tmp/21gk5WXdQu.c:25:37: note: in expansion of macro 'LEN'
25 | printf("Length of int : %d\n", LEN(i)); // Output: 5
| ^~~
ERROR!
/tmp/21gk5WXdQu.c:15:46: error: subscripted value is neither array nor pointer nor vector
15 | default : sizeof(x)/sizeof((x)[0]) \
| ^
/tmp/21gk5WXdQu.c:26:37: note: in expansion of macro 'LEN'
26 | printf("Length of Ulong: %d\n", LEN(ul)); // Output: 20
| ^~~
Is this a bug or a feature? I've searched about it, I've tried differect versions of gcc, plenty of tricks, I even asked chatGPT (but I'm not sure if it halucinates or not), so... any idea why this is happening? thanks in advance for any help.
Upvotes: 2
Views: 102
Reputation: 223632
_Generic
selects one of the listed expressions. All of the listed items must be valid expressions. If x
is not an array or pointer, x[0]
is not a valid expression. _Generic
is not like a preprocessor directive that can conditionally ignore some code. All of the code in it must be grammatically valid.
Upvotes: 4