为函数定义符号模糊指针参数
Define sign ambiguous pointer parameter for a function
是否可以在 C and/or C++ 中为函数定义符号模糊指针参数?
例如,假设我有一个函数,它适用于 8 位变量的无符号和有符号类型,并且该函数将指向变量的指针设为 processed/manipulated。
我知道我可以使用 (unsigned char*) 或 (signed char*) 进行类型转换,但我正在寻找更清洁的东西。
unsigned char Var1;
signed char Var2;
void MyFunction(unsigned char* Var);
MyFunction(&Var2); // This creates an error
话虽如此,我想提出我的想法,即高于汇编语言的语言不应使用诸如 BYTE / WORD / DWORD 或 QWORD 之类的名称来定义具有显式符号类型的变量。我这样说是因为这些是用于装配的大小运算符,实际上并没有定义符号。登录程序集由所选指令选择。然而,我看到这些名称在 C/C++ 中无处不在,并且定义为未签名,至少在 windows 上是这样。这对我来说似乎是一种利益冲突...
如果两种对象的逻辑相同,最好的选择是使用函数模板。
template <typename T>
void MyFunction(T* Var);
如果您想限制该函数仅用于 8 位类型,您可以在实现中使用 static_assert
。
template <typename T>
void MyFunction(T* Var)
{
static_assert(sizeof(T) == 1, "Wrong type. Can only deal with 8-bit types.");
...
}
对于 C,您的选择有限。您可以在调用函数时进行不喜欢的类型转换:
void MyFunction(unsigned char* Var);
int main(void) {
unsigned char Var1 = 5U;
signed char Var2 = 5;
MyFunction(&Var1);
MyFunction((unsigned char *)&Var2);
}
您可以在函数本身中使用 void *
和类型转换,只是不要将错误类型的指针传递给它:
void MyFunction(void* Var);
int main(void) {
unsigned char Var1 = 5U;
signed char Var2 = 5;
MyFunction(&Var1);
MyFunction(&Var2);
}
或者,如果您真的想要超出此范围的东西,您可以使用 _Generic 宏自动为您进行类型转换。它可能是也可能不是 "best" 方法,但我认为它会实现您的目标。
#define MY_FUNCTION_HELPER(X) MyFunction( _Generic((X), \
char *: (unsigned char *)X, \
signed char *: (unsigned char *)X, \
unsigned char *: X \
) \
)
void MyFunction(unsigned char *Var);
int main(void) {
unsigned char Var1 = 5U;
signed char Var2 = 5;
MY_FUNCTION_HELPER(&Var1);
MY_FUNCTION_HELPER(&Var2);
}
最后一个通过使用 C11 引入的 _Generic
来工作,它允许一种多态形式根据控制表达式的类型使用不同的表达式。在这种情况下,如果 X
是 char *
或 signed char *
,它将执行到 unsigned char *
的类型转换。如果 X
已经是 unsigned char *
,它将保持原样。如果 X
是其他任何东西,它将无法编译,因为通用关联列表中没有其他类型。
是否可以在 C and/or C++ 中为函数定义符号模糊指针参数?
例如,假设我有一个函数,它适用于 8 位变量的无符号和有符号类型,并且该函数将指向变量的指针设为 processed/manipulated。
我知道我可以使用 (unsigned char*) 或 (signed char*) 进行类型转换,但我正在寻找更清洁的东西。
unsigned char Var1;
signed char Var2;
void MyFunction(unsigned char* Var);
MyFunction(&Var2); // This creates an error
话虽如此,我想提出我的想法,即高于汇编语言的语言不应使用诸如 BYTE / WORD / DWORD 或 QWORD 之类的名称来定义具有显式符号类型的变量。我这样说是因为这些是用于装配的大小运算符,实际上并没有定义符号。登录程序集由所选指令选择。然而,我看到这些名称在 C/C++ 中无处不在,并且定义为未签名,至少在 windows 上是这样。这对我来说似乎是一种利益冲突...
如果两种对象的逻辑相同,最好的选择是使用函数模板。
template <typename T>
void MyFunction(T* Var);
如果您想限制该函数仅用于 8 位类型,您可以在实现中使用 static_assert
。
template <typename T>
void MyFunction(T* Var)
{
static_assert(sizeof(T) == 1, "Wrong type. Can only deal with 8-bit types.");
...
}
对于 C,您的选择有限。您可以在调用函数时进行不喜欢的类型转换:
void MyFunction(unsigned char* Var);
int main(void) {
unsigned char Var1 = 5U;
signed char Var2 = 5;
MyFunction(&Var1);
MyFunction((unsigned char *)&Var2);
}
您可以在函数本身中使用 void *
和类型转换,只是不要将错误类型的指针传递给它:
void MyFunction(void* Var);
int main(void) {
unsigned char Var1 = 5U;
signed char Var2 = 5;
MyFunction(&Var1);
MyFunction(&Var2);
}
或者,如果您真的想要超出此范围的东西,您可以使用 _Generic 宏自动为您进行类型转换。它可能是也可能不是 "best" 方法,但我认为它会实现您的目标。
#define MY_FUNCTION_HELPER(X) MyFunction( _Generic((X), \
char *: (unsigned char *)X, \
signed char *: (unsigned char *)X, \
unsigned char *: X \
) \
)
void MyFunction(unsigned char *Var);
int main(void) {
unsigned char Var1 = 5U;
signed char Var2 = 5;
MY_FUNCTION_HELPER(&Var1);
MY_FUNCTION_HELPER(&Var2);
}
最后一个通过使用 C11 引入的 _Generic
来工作,它允许一种多态形式根据控制表达式的类型使用不同的表达式。在这种情况下,如果 X
是 char *
或 signed char *
,它将执行到 unsigned char *
的类型转换。如果 X
已经是 unsigned char *
,它将保持原样。如果 X
是其他任何东西,它将无法编译,因为通用关联列表中没有其他类型。