gpt4 book ai didi

c - `void *` 函数参数类型不一致的转换方法

转载 作者:行者123 更新时间:2023-12-01 15:45:20 25 4
gpt4 key购买 nike

注意:这个问题试图改进我试图问 here 的问题,但没有达到目的。
此外,我还看到了 thisthis 。他们讨论相似的概念,但不回答这些问题。

我的环境是 Windows 10,为了测试我使用了两个编译器,CLANGGCC

我通过 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;
}

上面评论中与标志相关的确切错误文本如下:

CLANG - 3.3 版

  • (a1) - ...错误:无法将指针转换为类型“float”

海湾合作委员会 - (tdm-1) 5.1.0

  • (b1) - ...错误:在需要浮点值的地方使用了指针值
  • (b2) - ...错误:无法将指针转换为类型“double”

供下面讨论引用

  • 方法 1 == type var = (type)val;
  • 方法2 == type var = *(type *)val;

我的结果表明转换 floatdouble 需要方法 2。
但是对于 charint 方法 2 似乎是可选的,即方法 1 编译得很好,并且似乎始终如一地工作。

问题:

  • void * 函数中恢复一个值似乎参数应该总是需要方法 2,那么为什么方法 1(看起来to) 使用charint 类型?这是未定义的行为吗?

  • 如果方法 1 适用于 charint,为什么它至少不能适用于 float 类型?这不是因为它们的大小不同,即:sizeof(float) == sizeof(int) == sizeof(int *) == sizeof(float *)。是因为严格的别名违规吗?

最佳答案

C standard明确允许指针和整数类型之间的转换。这在第 6.3.2.3 节中关于指针转换有详细说明:

5 An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.

6 Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.

假设您在将整数类型传递给函数时将其转换为 void *,然后将其转换回正确的整数类型,这可以完成提供实现允许它。特别是 GCC 将允许这样做,假设所讨论的整数类型至少与 void * 一样大。

这就是转换适用于 charint 情况的原因,但是您需要传入值(转换为 void *) 而不是地址。

例如,如果您这样调用函数:

func4((void *)123, INT);

那么函数可以这样做:

int val = (int)a;

val 将包含值 123。但是如果您这样调用它:

int x = 123;
func4(&x, INT);

然后函数中的 val 将包含 main 中的 x 的地址转换为整数值。

根据第 6.5.4p4 节关于转换运算符的规定,明确不允许在指针类型和浮点类型之间进行转换:

A pointer type shall not be converted to any floating type. A floating type shall not be converted to any pointer type.

当然,通过 void * 传递值最安全的方法是将值存储在适当类型的变量中,传递其地址,然后转换 void * 在函数中返回正确的指针类型。这保证有效。

关于c - `void *` 函数参数类型不一致的转换方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59754887/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com