如何避免在多态打印宏中使用#if
how can I avoid the use of #if in a polymorphic print macro
让我们尝试运行下面的代码:
#include <stdio.h>
#define MY_MACRO1(isArray,y) do { \
if(isArray) \
printf("%d", y[0]); \
else \
printf("%d", y); \
}while(0)
int main()
{
int a = 38;
int b[]={42};
MY_MACRO1(0,a);
return 0;
}
它returns错误:
main.c: In function ‘main’:
main.c:12:39: error: subscripted value is neither array nor pointer nor vector
printf("%d", y[0]); \
好的,所以我们需要一个#if 语句来 运行 y[0] 只有当变量是一个数组时:
#define MY_MACRO2(isArray,y) do { \
#if isArray \
printf("%d", y[0]); \
#else \
printf("%d", y); \
#endif \
}while(0)
int main()
{
int a = 38;
int b[]={42};
MY_MACRO2(0,a);
return 0;
}
但是 returns :
main.c:11:28: error: '#' is not followed by a macro parameter
#define MY_MACRO2(isArray,y) do { \
有没有办法在宏中调用#if 语句?
如果没有,我怎么能做这样的事情?
注意:我使用的是 IAR 8.20.2
(这个没有帮助)
我想知道为什么我不想使用 2 个不同的宏是因为我需要这样做(伪代码):
myFunction(int or array):
doSomethingWhereIntAndArrayBehavesDifferentlyLikePrintf();
doSomethingelse();
doSomethingelse();
doSomethingWhereIntAndArrayBehavesDifferentlyLikePrintf();
doSomethingelse();
- 它非常方便:您可以分解代码。
- 这是一种实现多态性的方式。
- 它模仿了 C++ 模板功能。
您可以使用 BOOST_PP_IF
:
#include <boost/preprocessor/if.hpp>
#define MY_MACRO1(isArray,y) printf("%d", BOOST_PP_IF(isArray, (y)[0], (y)))
首先让我说一下,我认为您不应该为此使用宏。您应该有 2 个单独的函数,可能还有额外的 _Generic
表达式,如 Lundins answer 中所示。
但是,可以使用多个宏定义:
#define MY_MACRO(isArray,y) MY_MACRO_ ## isArray (y)
#define MY_MACRO_0(y) printf("%d", y)
#define MY_MACRO_1(y) printf("%d", y[0])
Is there anyway to call a #if statement inside a macro?
不可能。
if not, how can I do such a thing?
你可以使用 C11 _Generic:
#include <stdio.h>
void int_func (int obj)
{
printf("%d\n", obj);
}
void int_arr_func (const int* obj)
{
printf("%d\n", obj[0]);
}
void float_func (float obj)
{
printf("%f\n", obj);
}
#define MY_MACRO2(y) _Generic((y), \
int: int_func, \
int*: int_arr_func, \
float: float_func ) (y)
int main (void)
{
int a = 38;
int b[]={42};
float pi = 3.14f;
MY_MACRO2(a);
MY_MACRO2(b);
MY_MACRO2(pi);
return 0;
}
总结一下,另一个解决方法是使用 VLA 和宏。
使用 _Generic
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
static inline void printNonArray_u32 (uint32_t obj)
{
printf("interger >> uint32_t : %u\n",obj);
}
static inline void printNonArray_u16 (uint16_t obj)
{
printf("interger >> uint16_t : %u\n",obj);
}
static inline void printNonArray_u8 (uint8_t obj)
{
printf("interger >> uint8_t : %d\n",obj);
}
static inline void printArray_u32 (const uint32_t* obj)
{
printf("array >> uint32_t : ");
for(uint32_t i = 0 ; i<sizeof(obj)/sizeof(uint32_t) ; i++ )
printf("%d - ",(uint32_t)obj[i]);
printf("\n");
}
static inline void printArray_u16 (const uint16_t* obj)
{
printf("array >> uint16_t : ");
for(uint32_t i = 0 ; i<sizeof(obj)/sizeof(uint16_t) ; i++ )
printf("%d - ",(uint16_t)obj[i]);
printf("\n");
}
static inline void printArray_u8(const uint8_t* obj)
{
printf("array >> uint8_t : ");
for(uint32_t i = 0 ; i<sizeof(obj)/sizeof(uint8_t) ; i++ )
printf("%d - ",(uint8_t)obj[i]);
printf("\n");
}
#define MY_POLYMORPHIC_PRINT2(y) _Generic((y), \
uint32_t: printNonArray_u32, \
uint32_t*: printArray_u32, \
uint16_t: printNonArray_u16, \
uint16_t*: printArray_u16, \
uint8_t: printNonArray_u8, \
uint8_t*: printArray_u8 ) (y)
int main()
{
uint32_t i1 = 257;
uint16_t i2 = 257;
uint8_t i3 = 25;
uint32_t a1[]={42,43,44,257};
uint16_t a2[]={22,23,24,257};
uint8_t a3[]={12,13,14,25};
printf("MY_POLYMORPHIC_PRINT2 - _Generic\n");
MY_POLYMORPHIC_PRINT2(i1); //interger >> uint32_t : 257 >> OK
MY_POLYMORPHIC_PRINT2(i2); //interger >> uint16_t : 257 >> OK
MY_POLYMORPHIC_PRINT2(i3); //interger >> uint8_t : 25 >> OK
MY_POLYMORPHIC_PRINT2(a1); //array >> uint32_t : 42 - 43 - >> FAILS
MY_POLYMORPHIC_PRINT2(a2); //array >> uint16_t : 22 - 23 - 24 - 257 - >> OK
MY_POLYMORPHIC_PRINT2(a3); //array >> uint8_t : 12 - 13 - 14 - 25 - 253 - 127 - 0 - 0 - >> FAILS
return 0;
}
优点:
- 简单的宏+简单的函数
- 你不需要 C++ 库
- 你不再需要"isArray"
- 你不需要#if
- 类型安全
缺点:
- 如何获取数组大小? --> 在没有
的情况下给出了一些不好的结果
- 限于C11
使用 VLA(无 ##)
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define MY_POLYMORPHIC_PRINT1(y, type) do { \
if((sizeof(y)/sizeof(type) != 1) && (sizeof(y)/sizeof(type) != sizeof(y))) \
{ \
type arrayBuffer[sizeof(y)/sizeof(type)]; \
memcpy(&arrayBuffer,&y,sizeof(y)); \
printf("array >> "#type" : "); \
for(uint32_t i = 0 ; i<sizeof(y)/sizeof(type) ; i++ ) \
printf("%d - ",arrayBuffer[i]); \
printf("\n"); \
} \
else \
{ \
type intBuffer = (type)*((type*)(&y)); \
printf("integer >> "#type" : %d\n",intBuffer); \
} \
}while(0)
int main()
{
uint32_t i1 = 257;
uint16_t i2 = 257;
uint8_t i3 = 25;
uint32_t a1[]={42,43,44,257};
uint16_t a2[]={22,23,24,257};
uint8_t a3[]={12,13,14,25};
printf("MY_POLYMORPHIC_PRINT1 - VLA\n");
MY_POLYMORPHIC_PRINT1(i1,uint32_t);// integer >> uint32_t : 257 >> OK
MY_POLYMORPHIC_PRINT1(i2,uint16_t);// integer >> uint16_t : 257 >> OK
MY_POLYMORPHIC_PRINT1(i3,uint8_t); // integer >> uint8_t : 25 >> OK
MY_POLYMORPHIC_PRINT1(i1,uint8_t); // integer >> uint8_t : 1 >> POK wrong type, casting is working
MY_POLYMORPHIC_PRINT1(a1,uint32_t);// array >> uint32_t : 42 - 43 - 44 - 257 - >> OK
MY_POLYMORPHIC_PRINT1(a2,uint16_t);// array >> uint16_t : 22 - 23 - 24 - 257 - >> OK
MY_POLYMORPHIC_PRINT1(a3,uint8_t); // integer >> uint8_t : 12 >> FAILS
MY_POLYMORPHIC_PRINT1(a1,uint16_t); // integer >> uint16_t : 42 - 0 - 43 - 0 - 44 - 0 - 257 - 0 - >> POK wrong type, casting is somewhat working
return 0;
}
优点:
- 灵活
- 兼容性:C99、C11(VLA 选项)...
- 只有一个(丑陋的)宏
- 你不需要 C++ 库
- 你不再需要"isArray"
- 你不需要数组大小作为参数
- 你不需要#if
缺点:
- 类型不安全 --> 给出一些不好的结果
- 在 C99 之前不兼容
- 需要类型信息
使用 VLA + ##(字符串连接宏)
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define MY_VLA_PRINT_ARRAY(y, type) do{\
type arrayBuffer[sizeof(y)/sizeof(type)]; \
memcpy(&arrayBuffer,&y,sizeof(y)); \
printf("array >> "#type" : "); \
for(uint32_t i = 0 ; i<sizeof(y)/sizeof(type) ; i++ ) \
printf("%d - ",arrayBuffer[i]); \
printf("\n"); \
}while(0)
#define MY_VLA_PRINT_NOT_ARRAY(y, type) do{\
type intBuffer = (type)*((type*)(&y)); \
printf("integer >> "#type" : %d\n",intBuffer); \
}while(0)
#define MY_POLYMORPHIC_PRINT3( y, isArray, type) do { \
MY_VLA_PRINT_ ## isArray (y, type); \
}while(0)
int main()
{
uint32_t i1 = 257;
uint16_t i2 = 257;
uint8_t i3 = 25;
uint32_t a1[]={42,43,44,257};
uint16_t a2[]={22,23,24,257};
uint8_t a3[]={12,13,14,25};
printf("MY_POLYMORPHIC_PRINT3 - ## + VLA\n");
MY_POLYMORPHIC_PRINT3(i1,NOT_ARRAY,uint32_t); // integer >> uint32_t : 257 >> OK
MY_POLYMORPHIC_PRINT3(i2,NOT_ARRAY,uint16_t); // integer >> uint16_t : 257 >> OK
MY_POLYMORPHIC_PRINT3(i3,NOT_ARRAY,uint8_t); // integer >> uint8_t : 25 >> OK
MY_POLYMORPHIC_PRINT3(i1,NOT_ARRAY,uint8_t); // integer >> uint8_t : 1 >> POK wrong type, casting is working
MY_POLYMORPHIC_PRINT3(i1,ARRAY,uint8_t); // array >> uint8_t : 1 - 1 - 0 - 0 - >> POK (does not crash)
MY_POLYMORPHIC_PRINT3(a1,ARRAY,uint32_t); // array >> uint32_t : 42 - 43 - 44 - 257 - >> OK
MY_POLYMORPHIC_PRINT3(a2,ARRAY,uint16_t); // array >> uint16_t : 22 - 23 - 24 - 257 - >> OK
MY_POLYMORPHIC_PRINT3(a3,ARRAY,uint8_t); // array >> uint8_t : 12 - 13 - 14 - 25 - >> OK
MY_POLYMORPHIC_PRINT3(a1,ARRAY,uint16_t); // array >> uint16_t : 42 - 0 - 43 - 0 - 44 - 0 - 257 - 0 - >> POK wrong type, casting is somewhat working
MY_POLYMORPHIC_PRINT3(a1,NOT_ARRAY,uint16_t); // integer >> uint16_t : 42 >> POK (does not crash)
return 0;
}
优点:
- 唯一适用于所有测试用例的解决方案
- 非常简单的宏
- 你不需要 C++ 库
- 你不需要#if
缺点:
- 在 C99 之前不兼容
- 需要 isArray
- 需要类型信息
- 不是类型安全的 --> 但没有给出一些太糟糕的结果
没有 VLA 的宏##:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define MY_NON_VLA_PRINT_ARRAY_U32(y) do{\
printf("array >> uint32_t : "); \
for(uint32_t i = 0 ; i< sizeof(y) / sizeof(uint32_t) ; i++ ) \
printf("%d - ",(uint32_t)*((uint32_t*)&y+(uint32_t*)i)); \
printf("\n"); \
}while(0)
#define MY_NON_VLA_PRINT_ARRAY_U16(y) do{\
printf("array >> uint16_t : "); \
for(uint32_t i = 0 ; i< sizeof(y) / sizeof(uint16_t) ; i++ ) \
printf("%d - ",(uint16_t)*((uint16_t*)&y+(uint16_t*)i)); \
printf("\n"); \
}while(0)
#define MY_NON_VLA_PRINT_ARRAY_U8(y) do{\
printf("array >> uint8_t : "); \
for(uint32_t i = 0 ; i< sizeof(y) / sizeof(uint8_t) ; i++ ) \
printf("%d - ",(uint8_t)*((uint8_t*)&y+(uint8_t*)i)); \
printf("\n"); \
}while(0)
#define MY_NON_VLA_PRINT_NOT_ARRAY_U32(y) do{\
printf("integer >> uint32_t : %d\n",(uint32_t)y); \
}while(0)
#define MY_NON_VLA_PRINT_NOT_ARRAY_U16(y) do{\
printf("integer >> uint16_t : %d\n",(uint16_t)y); \
}while(0)
#define MY_NON_VLA_PRINT_NOT_ARRAY_U8(y) do{\
printf("integer >> uint8_t : %d\n",(uint8_t)y); \
}while(0)
#define MY_POLYMORPHIC_PRINT4( y, isArray, type) do { \
MY_NON_VLA_PRINT_ ## isArray ## _ ## type (y); \
}while(0)
int main()
{
uint32_t i1 = 257;
uint16_t i2 = 257;
uint8_t i3 = 25;
uint32_t a1[]={42,43,44,257};
uint16_t a2[]={22,23,24,257};
uint8_t a3[]={12,13,14,25};
printf("MY_POLYMORPHIC_PRINT4 - ## + no VLA\n");
MY_POLYMORPHIC_PRINT4(i1,NOT_ARRAY,U32);
MY_POLYMORPHIC_PRINT4(i2,NOT_ARRAY,U16);
MY_POLYMORPHIC_PRINT4(i3,NOT_ARRAY,U8);
MY_POLYMORPHIC_PRINT4(i1,NOT_ARRAY,U8);
MY_POLYMORPHIC_PRINT4(i1,ARRAY,U8);
MY_POLYMORPHIC_PRINT4(a1,ARRAY,U32);
MY_POLYMORPHIC_PRINT4(a2,ARRAY,U16);
MY_POLYMORPHIC_PRINT4(a3,ARRAY,U8);
MY_POLYMORPHIC_PRINT4(a1,ARRAY,U16);
MY_POLYMORPHIC_PRINT4(a1,NOT_ARRAY,U16);
//does not compile:
// error: invalid operands to binary + (have ‘uint32_t * {aka unsigned int *}’ and ‘uint32_t * {aka unsigned int *}’)
// printf("%d - ",(uint32_t)*((uint32_t*)&y+(uint32_t*)i)); \
// error: invalid operands to binary + (have ‘uint16_t * {aka short unsigned int *}’ and ‘uint16_t * {aka short unsigned int *}’)
// printf("%d - ",(uint16_t)*((uint16_t*)&y+(uint16_t*)i)); \
// error: invalid operands to binary + (have ‘uint8_t * {aka unsigned char *}’ and ‘uint8_t * {aka unsigned char *}’)
// printf("%d - ",(uint8_t)*((uint8_t*)&y+(uint8_t*)i)); \
return 0;
}
优点:
- 兼容 C99 之前的版本
- 你不需要 C++ 库
- 你不需要#if
缺点:
- 不编译!
- 很多宏
- 需要 isArray
- 需要类型信息
- 不是类型安全的
让我们尝试运行下面的代码:
#include <stdio.h>
#define MY_MACRO1(isArray,y) do { \
if(isArray) \
printf("%d", y[0]); \
else \
printf("%d", y); \
}while(0)
int main()
{
int a = 38;
int b[]={42};
MY_MACRO1(0,a);
return 0;
}
它returns错误:
main.c: In function ‘main’:
main.c:12:39: error: subscripted value is neither array nor pointer nor vector
printf("%d", y[0]); \
好的,所以我们需要一个#if 语句来 运行 y[0] 只有当变量是一个数组时:
#define MY_MACRO2(isArray,y) do { \
#if isArray \
printf("%d", y[0]); \
#else \
printf("%d", y); \
#endif \
}while(0)
int main()
{
int a = 38;
int b[]={42};
MY_MACRO2(0,a);
return 0;
}
但是 returns :
main.c:11:28: error: '#' is not followed by a macro parameter
#define MY_MACRO2(isArray,y) do { \
有没有办法在宏中调用#if 语句? 如果没有,我怎么能做这样的事情?
注意:我使用的是 IAR 8.20.2
(这个
我想知道为什么我不想使用 2 个不同的宏是因为我需要这样做(伪代码):
myFunction(int or array):
doSomethingWhereIntAndArrayBehavesDifferentlyLikePrintf();
doSomethingelse();
doSomethingelse();
doSomethingWhereIntAndArrayBehavesDifferentlyLikePrintf();
doSomethingelse();
- 它非常方便:您可以分解代码。
- 这是一种实现多态性的方式。
- 它模仿了 C++ 模板功能。
您可以使用 BOOST_PP_IF
:
#include <boost/preprocessor/if.hpp>
#define MY_MACRO1(isArray,y) printf("%d", BOOST_PP_IF(isArray, (y)[0], (y)))
首先让我说一下,我认为您不应该为此使用宏。您应该有 2 个单独的函数,可能还有额外的 _Generic
表达式,如 Lundins answer 中所示。
但是,可以使用多个宏定义:
#define MY_MACRO(isArray,y) MY_MACRO_ ## isArray (y)
#define MY_MACRO_0(y) printf("%d", y)
#define MY_MACRO_1(y) printf("%d", y[0])
Is there anyway to call a #if statement inside a macro?
不可能。
if not, how can I do such a thing?
你可以使用 C11 _Generic:
#include <stdio.h>
void int_func (int obj)
{
printf("%d\n", obj);
}
void int_arr_func (const int* obj)
{
printf("%d\n", obj[0]);
}
void float_func (float obj)
{
printf("%f\n", obj);
}
#define MY_MACRO2(y) _Generic((y), \
int: int_func, \
int*: int_arr_func, \
float: float_func ) (y)
int main (void)
{
int a = 38;
int b[]={42};
float pi = 3.14f;
MY_MACRO2(a);
MY_MACRO2(b);
MY_MACRO2(pi);
return 0;
}
总结一下,另一个解决方法是使用 VLA 和宏。
使用 _Generic
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
static inline void printNonArray_u32 (uint32_t obj)
{
printf("interger >> uint32_t : %u\n",obj);
}
static inline void printNonArray_u16 (uint16_t obj)
{
printf("interger >> uint16_t : %u\n",obj);
}
static inline void printNonArray_u8 (uint8_t obj)
{
printf("interger >> uint8_t : %d\n",obj);
}
static inline void printArray_u32 (const uint32_t* obj)
{
printf("array >> uint32_t : ");
for(uint32_t i = 0 ; i<sizeof(obj)/sizeof(uint32_t) ; i++ )
printf("%d - ",(uint32_t)obj[i]);
printf("\n");
}
static inline void printArray_u16 (const uint16_t* obj)
{
printf("array >> uint16_t : ");
for(uint32_t i = 0 ; i<sizeof(obj)/sizeof(uint16_t) ; i++ )
printf("%d - ",(uint16_t)obj[i]);
printf("\n");
}
static inline void printArray_u8(const uint8_t* obj)
{
printf("array >> uint8_t : ");
for(uint32_t i = 0 ; i<sizeof(obj)/sizeof(uint8_t) ; i++ )
printf("%d - ",(uint8_t)obj[i]);
printf("\n");
}
#define MY_POLYMORPHIC_PRINT2(y) _Generic((y), \
uint32_t: printNonArray_u32, \
uint32_t*: printArray_u32, \
uint16_t: printNonArray_u16, \
uint16_t*: printArray_u16, \
uint8_t: printNonArray_u8, \
uint8_t*: printArray_u8 ) (y)
int main()
{
uint32_t i1 = 257;
uint16_t i2 = 257;
uint8_t i3 = 25;
uint32_t a1[]={42,43,44,257};
uint16_t a2[]={22,23,24,257};
uint8_t a3[]={12,13,14,25};
printf("MY_POLYMORPHIC_PRINT2 - _Generic\n");
MY_POLYMORPHIC_PRINT2(i1); //interger >> uint32_t : 257 >> OK
MY_POLYMORPHIC_PRINT2(i2); //interger >> uint16_t : 257 >> OK
MY_POLYMORPHIC_PRINT2(i3); //interger >> uint8_t : 25 >> OK
MY_POLYMORPHIC_PRINT2(a1); //array >> uint32_t : 42 - 43 - >> FAILS
MY_POLYMORPHIC_PRINT2(a2); //array >> uint16_t : 22 - 23 - 24 - 257 - >> OK
MY_POLYMORPHIC_PRINT2(a3); //array >> uint8_t : 12 - 13 - 14 - 25 - 253 - 127 - 0 - 0 - >> FAILS
return 0;
}
优点:
- 简单的宏+简单的函数
- 你不需要 C++ 库
- 你不再需要"isArray"
- 你不需要#if
- 类型安全
缺点:
- 如何获取数组大小? --> 在没有 的情况下给出了一些不好的结果
- 限于C11
使用 VLA(无 ##)
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define MY_POLYMORPHIC_PRINT1(y, type) do { \
if((sizeof(y)/sizeof(type) != 1) && (sizeof(y)/sizeof(type) != sizeof(y))) \
{ \
type arrayBuffer[sizeof(y)/sizeof(type)]; \
memcpy(&arrayBuffer,&y,sizeof(y)); \
printf("array >> "#type" : "); \
for(uint32_t i = 0 ; i<sizeof(y)/sizeof(type) ; i++ ) \
printf("%d - ",arrayBuffer[i]); \
printf("\n"); \
} \
else \
{ \
type intBuffer = (type)*((type*)(&y)); \
printf("integer >> "#type" : %d\n",intBuffer); \
} \
}while(0)
int main()
{
uint32_t i1 = 257;
uint16_t i2 = 257;
uint8_t i3 = 25;
uint32_t a1[]={42,43,44,257};
uint16_t a2[]={22,23,24,257};
uint8_t a3[]={12,13,14,25};
printf("MY_POLYMORPHIC_PRINT1 - VLA\n");
MY_POLYMORPHIC_PRINT1(i1,uint32_t);// integer >> uint32_t : 257 >> OK
MY_POLYMORPHIC_PRINT1(i2,uint16_t);// integer >> uint16_t : 257 >> OK
MY_POLYMORPHIC_PRINT1(i3,uint8_t); // integer >> uint8_t : 25 >> OK
MY_POLYMORPHIC_PRINT1(i1,uint8_t); // integer >> uint8_t : 1 >> POK wrong type, casting is working
MY_POLYMORPHIC_PRINT1(a1,uint32_t);// array >> uint32_t : 42 - 43 - 44 - 257 - >> OK
MY_POLYMORPHIC_PRINT1(a2,uint16_t);// array >> uint16_t : 22 - 23 - 24 - 257 - >> OK
MY_POLYMORPHIC_PRINT1(a3,uint8_t); // integer >> uint8_t : 12 >> FAILS
MY_POLYMORPHIC_PRINT1(a1,uint16_t); // integer >> uint16_t : 42 - 0 - 43 - 0 - 44 - 0 - 257 - 0 - >> POK wrong type, casting is somewhat working
return 0;
}
优点:
- 灵活
- 兼容性:C99、C11(VLA 选项)...
- 只有一个(丑陋的)宏
- 你不需要 C++ 库
- 你不再需要"isArray"
- 你不需要数组大小作为参数
- 你不需要#if
缺点:
- 类型不安全 --> 给出一些不好的结果
- 在 C99 之前不兼容
- 需要类型信息
使用 VLA + ##(字符串连接宏)
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define MY_VLA_PRINT_ARRAY(y, type) do{\
type arrayBuffer[sizeof(y)/sizeof(type)]; \
memcpy(&arrayBuffer,&y,sizeof(y)); \
printf("array >> "#type" : "); \
for(uint32_t i = 0 ; i<sizeof(y)/sizeof(type) ; i++ ) \
printf("%d - ",arrayBuffer[i]); \
printf("\n"); \
}while(0)
#define MY_VLA_PRINT_NOT_ARRAY(y, type) do{\
type intBuffer = (type)*((type*)(&y)); \
printf("integer >> "#type" : %d\n",intBuffer); \
}while(0)
#define MY_POLYMORPHIC_PRINT3( y, isArray, type) do { \
MY_VLA_PRINT_ ## isArray (y, type); \
}while(0)
int main()
{
uint32_t i1 = 257;
uint16_t i2 = 257;
uint8_t i3 = 25;
uint32_t a1[]={42,43,44,257};
uint16_t a2[]={22,23,24,257};
uint8_t a3[]={12,13,14,25};
printf("MY_POLYMORPHIC_PRINT3 - ## + VLA\n");
MY_POLYMORPHIC_PRINT3(i1,NOT_ARRAY,uint32_t); // integer >> uint32_t : 257 >> OK
MY_POLYMORPHIC_PRINT3(i2,NOT_ARRAY,uint16_t); // integer >> uint16_t : 257 >> OK
MY_POLYMORPHIC_PRINT3(i3,NOT_ARRAY,uint8_t); // integer >> uint8_t : 25 >> OK
MY_POLYMORPHIC_PRINT3(i1,NOT_ARRAY,uint8_t); // integer >> uint8_t : 1 >> POK wrong type, casting is working
MY_POLYMORPHIC_PRINT3(i1,ARRAY,uint8_t); // array >> uint8_t : 1 - 1 - 0 - 0 - >> POK (does not crash)
MY_POLYMORPHIC_PRINT3(a1,ARRAY,uint32_t); // array >> uint32_t : 42 - 43 - 44 - 257 - >> OK
MY_POLYMORPHIC_PRINT3(a2,ARRAY,uint16_t); // array >> uint16_t : 22 - 23 - 24 - 257 - >> OK
MY_POLYMORPHIC_PRINT3(a3,ARRAY,uint8_t); // array >> uint8_t : 12 - 13 - 14 - 25 - >> OK
MY_POLYMORPHIC_PRINT3(a1,ARRAY,uint16_t); // array >> uint16_t : 42 - 0 - 43 - 0 - 44 - 0 - 257 - 0 - >> POK wrong type, casting is somewhat working
MY_POLYMORPHIC_PRINT3(a1,NOT_ARRAY,uint16_t); // integer >> uint16_t : 42 >> POK (does not crash)
return 0;
}
优点:
- 唯一适用于所有测试用例的解决方案
- 非常简单的宏
- 你不需要 C++ 库
- 你不需要#if
缺点:
- 在 C99 之前不兼容
- 需要 isArray
- 需要类型信息
- 不是类型安全的 --> 但没有给出一些太糟糕的结果
没有 VLA 的宏##:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define MY_NON_VLA_PRINT_ARRAY_U32(y) do{\
printf("array >> uint32_t : "); \
for(uint32_t i = 0 ; i< sizeof(y) / sizeof(uint32_t) ; i++ ) \
printf("%d - ",(uint32_t)*((uint32_t*)&y+(uint32_t*)i)); \
printf("\n"); \
}while(0)
#define MY_NON_VLA_PRINT_ARRAY_U16(y) do{\
printf("array >> uint16_t : "); \
for(uint32_t i = 0 ; i< sizeof(y) / sizeof(uint16_t) ; i++ ) \
printf("%d - ",(uint16_t)*((uint16_t*)&y+(uint16_t*)i)); \
printf("\n"); \
}while(0)
#define MY_NON_VLA_PRINT_ARRAY_U8(y) do{\
printf("array >> uint8_t : "); \
for(uint32_t i = 0 ; i< sizeof(y) / sizeof(uint8_t) ; i++ ) \
printf("%d - ",(uint8_t)*((uint8_t*)&y+(uint8_t*)i)); \
printf("\n"); \
}while(0)
#define MY_NON_VLA_PRINT_NOT_ARRAY_U32(y) do{\
printf("integer >> uint32_t : %d\n",(uint32_t)y); \
}while(0)
#define MY_NON_VLA_PRINT_NOT_ARRAY_U16(y) do{\
printf("integer >> uint16_t : %d\n",(uint16_t)y); \
}while(0)
#define MY_NON_VLA_PRINT_NOT_ARRAY_U8(y) do{\
printf("integer >> uint8_t : %d\n",(uint8_t)y); \
}while(0)
#define MY_POLYMORPHIC_PRINT4( y, isArray, type) do { \
MY_NON_VLA_PRINT_ ## isArray ## _ ## type (y); \
}while(0)
int main()
{
uint32_t i1 = 257;
uint16_t i2 = 257;
uint8_t i3 = 25;
uint32_t a1[]={42,43,44,257};
uint16_t a2[]={22,23,24,257};
uint8_t a3[]={12,13,14,25};
printf("MY_POLYMORPHIC_PRINT4 - ## + no VLA\n");
MY_POLYMORPHIC_PRINT4(i1,NOT_ARRAY,U32);
MY_POLYMORPHIC_PRINT4(i2,NOT_ARRAY,U16);
MY_POLYMORPHIC_PRINT4(i3,NOT_ARRAY,U8);
MY_POLYMORPHIC_PRINT4(i1,NOT_ARRAY,U8);
MY_POLYMORPHIC_PRINT4(i1,ARRAY,U8);
MY_POLYMORPHIC_PRINT4(a1,ARRAY,U32);
MY_POLYMORPHIC_PRINT4(a2,ARRAY,U16);
MY_POLYMORPHIC_PRINT4(a3,ARRAY,U8);
MY_POLYMORPHIC_PRINT4(a1,ARRAY,U16);
MY_POLYMORPHIC_PRINT4(a1,NOT_ARRAY,U16);
//does not compile:
// error: invalid operands to binary + (have ‘uint32_t * {aka unsigned int *}’ and ‘uint32_t * {aka unsigned int *}’)
// printf("%d - ",(uint32_t)*((uint32_t*)&y+(uint32_t*)i)); \
// error: invalid operands to binary + (have ‘uint16_t * {aka short unsigned int *}’ and ‘uint16_t * {aka short unsigned int *}’)
// printf("%d - ",(uint16_t)*((uint16_t*)&y+(uint16_t*)i)); \
// error: invalid operands to binary + (have ‘uint8_t * {aka unsigned char *}’ and ‘uint8_t * {aka unsigned char *}’)
// printf("%d - ",(uint8_t)*((uint8_t*)&y+(uint8_t*)i)); \
return 0;
}
优点:
- 兼容 C99 之前的版本
- 你不需要 C++ 库
- 你不需要#if
缺点:
- 不编译!
- 很多宏
- 需要 isArray
- 需要类型信息
- 不是类型安全的