【发布时间】:2020-01-15 15:45:00
【问题描述】:
注意:这个问题试图改善我试图问here 的问题,但没有达到。
另外,我见过this 和this。他们讨论类似的概念,但不回答这些问题。
我的环境是 Windows 10,为了测试我使用了两个编译器,CLANG 和 GCC。
我通过void * 函数参数传递变量,并且需要转换它们。我想就我在不同类型的方法之间看到的不一致获得一些反馈。
以下是使用void * 参数和用于指示传入类型的枚举值参数适应多种输入类型的测试函数的精简描述:
void func(void *a, int type)
{
switch(type) {
case CHAR://char
char cVar1 = (char)a; //compiles with no warnings/errors, seems to work
char cVar2 = *(char *)a; //compiles with no warnings/errors, seems to work
break;
case INT://int
int iVar1 = (int)a; //compiles with no warnings/errors, seems to work
int iVar2 = *(int *)a; //compiles with no warnings/errors, seems to work
break;
case FLT://float
float fVar1 = (float)a; //compile error: (a1)(b1)
float fVar2 = *(float *)a; //requires this method
case DBL://double
double dVar1 = (double)a; //compile error: (a1)(b1)(b2)
double dVar2 = *(double *)a;//this appears to be correct approach
break;
};
}
调用方法:
int main(void)
{
char c = 'P';
int d = 1024;
float e = 14.5;
double f = 0.0000012341;
double g = 0.0001234567;
void *pG = &g;
func(&c, CHAR);//CHAR defined in enumeration, typical
func(&d, INT);
func(&e, FLT);
func(&f, DBL);
func(pG, DBL);
return 0;
}
与上述 cmets 中的标志相关的确切错误文本如下:
CLANG - 3.3 版
- (a1) - ...错误:指针不能转换为“float”类型
gcc - (tdm-1) 5.1.0
- (b1) - ...错误:指针值在预期为浮点值的地方使用
- (b2) - ...错误:指针不能转换为“double”类型
供下文讨论参考
- 方法 1 ==
type var = (type)val; - 方法2 ==
type var = *(type *)val;
我的结果表明转换float & double 需要方法2。
但是对于 char 和 int 来说,方法 2 似乎是可选的,即方法 1 编译得很好,并且似乎可以始终如一地工作。
问题:
似乎从
void *函数中恢复值 参数应该总是需要方法2,那么为什么方法1(似乎 to) 使用char和int类型?这是未定义的行为吗?如果方法 1 适用于
char和int,为什么它至少不适用于float类型?这不是因为它们的大小不同,即:sizeof(float) == sizeof(int) == sizeof(int *) == sizeof(float *)。是因为严格的别名违规吗?
【问题讨论】:
-
我们不能在没有看到调用代码和真正的变量声明的情况下评论严格别名。严格的别名与指针转换几乎没有关系,而与左值访问有关。
-
@Lundin - 我将编辑添加...
-
您没有显示传递参数的调用,因此我们不知道您如何将它们转换为
void *。在任何情况下,void *和char或float之间的转换很可能不是您想要的。通常,您会将某个对象的 地址 传递给例程。因此例程接收到一个指针,该指针已转换为void *。然后例程应该将该指针转换为正确类型的 pointer,以便您再次获得对象的地址。然后使用*取消引用该指针以获取对象的值。 -
在
switch(type) ...中你应该使用CHAR等,而不是显式值0。 -
好吧,不管怎样,我认为很清楚,在 C 语言中你不能将指针转换为除整数之外的其他类型,仅仅是因为表示将是无用的并且实际上没有任何意义。另一方面,即使在某些架构上将指针表示为整数也是违反直觉的。
标签: c undefined-behavior void-pointers strict-aliasing