C 中的意外行为_具有复合文字的泛型

问题描述 投票:0回答:1

在 C 中使用

_Generic
和复合文字时,我遇到了意外的行为。看起来
_Generic
选择第一个包含复合文字的情况,无论它是否与表达式的实际类型匹配。即使其他情况应该更精确地匹配,也会发生这种情况。

考虑以下代码:

typedef struct { unsigned char _dummy_m[3]; } int24_t;

#define GET_VALUE_ADDRESS(v) _Generic((v), \
    int*:           &(v), \
    double:         &(double){v}, \
    int24_t:        &(v), \
    default:        &(v))

int main (void)
{
    int24_t val = {1,2,3};
    void* addr = GET_VALUE_ADDRESS(val); /* erroneous */
    return 0;
}

编译器是 MinGW-GCC Rev2,由 MSYS2 项目 10.3.0 构建,并具有以下 CMake 配置:

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_EXTENSIONS ON)

代码产生以下错误:

incompatible types when initializing type 'double' using type 'int24_t'

预期行为:

在此示例中,

v
的类型为
int24_t
,因此我希望
_Generic
匹配
int24_t
大小写并返回
&(v)

实际行为:

相反,编译器似乎总是选择第一个涉及复合文字的情况(在本例中为

&(double){v}
),无论
v
的类型如何。这会导致类型匹配不正确和意外的输出。

附加信息:

如果我删除复合文字并将其替换为常规地址操作,则

_Generic
按预期工作。仅当使用复合文字作为
_Generic
中的返回值时,才会出现此问题。

问题: 即使这不是

_Generic
本身的错误或怪癖,我得到的错误仍然毫无帮助。 这是一个已知的错误还是 _Generic 如何处理复合文字的限制?如果是这样,是否有任何解决方法,或者我在这种情况下滥用了
_Generic

c generics
1个回答
0
投票

看起来

_Generic
选择了第一个包含复合文字的情况......

_Generic
此处未选择任何大小写,或者更准确地说,编译器尚未将
_Generic
表达式解析为任何操作数。

错误消息来自分析整个

_Generic
表达式,如下所述。

incompatible types when initializing type 'double' using type 'int24_t'

_Generic
不是预处理器构造。它是 C 语言中的一个表达式,并且其列表中的所有表达式都必须是真表达式(具体来说,每个表达式都必须是形式语法中的赋值表达式)。当
v
val
时,
&(double){v}
&(double){val}
。该表达式由编译器分析,其中的复合文字尝试使用
double
初始化
val
val
是一个
int24_t
,您已将其定义为结构体。编译器正确报告尝试使用结构初始化
double
的错误。

此列表项稍后不会被

_Generic
选择这一事实是无关紧要的;编译器必须首先全面分析每个列表项。此项目无法分析。

这是一个已知的错误还是

_Generic
处理复合文字的限制?

不,这是编译器的正确行为,并且是源代码中的实际错误。

如果是这样,是否有任何解决方法,或者我在这种情况下滥用了

_Generic

虽然你的两个标签是

double
int24_t
,但我怀疑你想让它们成为
double *
int24_t *
。如果是这样,那么,在您将
_Generic
结果分配给
void *
的用例中,您可以简单地使用:

void *addr = &val;

或者,仅更改宏定义:

#define GET_VALUE_ADDRESS(v) &(v)
…
void *addr = GET_VALUE_ADDRESS(val);

如果这不能满足您的目的,您需要说明您的要求。

© www.soinside.com 2019 - 2024. All rights reserved.