C语言重载函数使用_Generic混合函数调用返回常量
Overload function in C language using _Generic mix function call with constants returning
我看到有两种写 _Generic
语句的方法:
A.
#define len(x) _Generic((x), char*:f1, int: f2, char: f3, double:f4) (x)
我想在 (x).
下划线
B.
#define len(x) _Generic((x), char*:f1(x), int: f2(x), char: f3(x), double:f4)
问题是在 B 的情况下,我得到了错误:
- 需要 char* 但参数是 int 类型
- f 的参数 1 的类型不兼容...
如果我想将函数与常量混合使用,我应该如何编写这个重载?
我正在尝试获取:
1 如果参数是 char 类型;
参数类型为 char * 时字符串的长度;
如果参数是int类型,小数位数(当参数为负数时可能加1);
如果参数是双精度类型,则 printf() 函数使用 %f 说明符生成的字符串的长度。
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'm trying to get:
假设编译器为任何输入采用所有路径。无论编译器采用哪条路径,它们都必须对任何输入都是“有效的”,即使只使用和评估一个表达式而其余的被丢弃,它们在技术上也必须是“有效的”。
#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。我最终在 strlen
中使用超级转换来处理 strlen(261.321)
情况 - 将 double
转换为指针,这样编译器就不会抱怨。在 "abc"
情况下,我希望演员表不修改指针值并不重要。这就是为什么为每种情况开发单独的功能会更容易的原因。您也可以(滥用)在泛型中使用可变函数参数来轻松删除任何强制转换并使用 va_arg
s.
在您的函数中处理它们
(小小自我提升:我最近通过developing type-safe-ish printf, with that library it would be just #define len(x) ysprint(NULL, 0, x)探索了_Generic
的限制,但是我已经看到双大小写的逗号后的位数不同于%f
printf
).
我看到有两种写 _Generic
语句的方法:
A.
#define len(x) _Generic((x), char*:f1, int: f2, char: f3, double:f4) (x)
我想在 (x).
下划线B.
#define len(x) _Generic((x), char*:f1(x), int: f2(x), char: f3(x), double:f4)
问题是在 B 的情况下,我得到了错误:
- 需要 char* 但参数是 int 类型
- f 的参数 1 的类型不兼容...
如果我想将函数与常量混合使用,我应该如何编写这个重载?
我正在尝试获取:
1 如果参数是 char 类型;
参数类型为 char * 时字符串的长度;
如果参数是int类型,小数位数(当参数为负数时可能加1);
如果参数是双精度类型,则 printf() 函数使用 %f 说明符生成的字符串的长度。
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'm trying to get:
假设编译器为任何输入采用所有路径。无论编译器采用哪条路径,它们都必须对任何输入都是“有效的”,即使只使用和评估一个表达式而其余的被丢弃,它们在技术上也必须是“有效的”。
#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。我最终在 strlen
中使用超级转换来处理 strlen(261.321)
情况 - 将 double
转换为指针,这样编译器就不会抱怨。在 "abc"
情况下,我希望演员表不修改指针值并不重要。这就是为什么为每种情况开发单独的功能会更容易的原因。您也可以(滥用)在泛型中使用可变函数参数来轻松删除任何强制转换并使用 va_arg
s.
(小小自我提升:我最近通过developing type-safe-ish printf, with that library it would be just #define len(x) ysprint(NULL, 0, x)探索了_Generic
的限制,但是我已经看到双大小写的逗号后的位数不同于%f
printf
).