C11 _通用用法 [英] C11 _Generic usage

查看:145
本文介绍了C11 _通用用法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图学习如何使用新的" C11通用表达式,但遇到了麻烦.

I was trying to learn how to use the "new" C11 Generic expressions but I ran into a wall.

考虑以下代码:

#include <stdlib.h>
#include <stdio.h>

#define test(X, Y, c) \
    _Generic((X), \
        double:     _Generic((Y), \
                        double * :  test_double, \
                        default: test_double \
                    ), \
        int:        _Generic((Y), \
                        int * : test_int, \
                        default: test_int \
                    ) \
    ) (X, Y, c)


int test_double(double a, double *b, int c);
int test_int(int a, int *b, int c);

int test_double(double a, double *b, int c) { return 1; }
int test_int(int a, int *b, int c) { return 2; }

int main()
{
    double *t = malloc(sizeof(double));
    int *s = malloc(sizeof(int));
    int a1 = test(3.4, t, 1);
    int i = 3;
    int a2 = test(i, s, 1);
    printf("%d\t", a1);
    printf("%d\n", a2);
    return 0;
 }

这一切都很好,我仍然看不到为什么"_Generic((Y),..."中的那些默认情况是必需的,而我可以在"_Generic((X),..)的末尾省略它". .."而没有任何后果.

This is all perfectly working, still I don't see why those default cases in "_Generic((Y), ..." are necessary while I can omit it at the end of "_Generic((X), ..." without consequences.

实际上,如果我删除了这两个默认值,则会收到错误消息(gcc 5.4.0),提示类型为'double *'的选择器与任何关联均不兼容" ,同时进行宏扩展" int a1 = test(3.4,t,1);和在宏扩展 test(i,s,1)

In fact, if I remove those two defaults I get an error (gcc 5.4.0) saying "selector of type ‘double *’ is not compatible with any association" while macro-expanding " int a1 = test(3.4, t, 1);" and the same thing with "int *" while macro-expanding test(i, s, 1)

默认"确实必要吗?还是我遗漏了一些东西? 在第一种情况下,为什么会这样呢?如果我只有test_double和test_int可以调用,那为什么我应该为一个永远都不能编译的东西设置一个默认的大小写呢?

Is "default" really necessary or am I missing something? In the first case, why the hell should it be? If I have only test_double and test_int that can be called why should I put a default case for something that should never even compile?

推荐答案

TL; DR

选择发生在编译时,但这并不意味着其他(未选择)的代码将被丢弃.它仍然必须有效,这意味着...

TL;DR

The selection happens at compile time, but this does not mean that the other (not selected) code is discarded. It still has to be valid, and this means that ...

如果不使用默认值,并且所有类型名称都不与控制表达式的类型兼容,则程序将无法编译.

If default is not used and none of the type-names are compatible with the type of the controlling expression, the program will not compile.

(来源)

那真是令人惊讶:

没有第一个Y"的默认大小写:

Without the default case for the "first Y":

#define test(X, Y, c) \
    _Generic((X), \
        double:     _Generic((Y), \
                        double * :  test_double \
                    ), \
        int:        _Generic((Y), \
                        int * : test_int, \
                        default: test_default \
                    ) \
    ) (X, Y, c)

我收到该错误:

prog.c:6:30:错误:类型为'int *'的'_Generic'选择器与任何关联都不兼容

prog.c:6:30: error: '_Generic' selector of type 'int *' is not compatible with any association

请注意,它抱怨一个不兼容的int *!为什么? 好吧,我们来看一下报告的行:

Note that it complains about an int * that is not compatible! Why? Well let's look at the reported line:

    int a2 = test(i, s, 1);

X的类型为intY的类型为int *.

X is of type int, and Y of type int *.

现在是重要的部分:扩展无条件发生.因此,即使X的类型为intX的第一个关联(当它的类型为double时)也必须是格式正确的程序.因此,以Yint *时,必须格式正确:

Now comes the important part: Expansions happens unconditionally. So even though X is of type int, the first association for X (when it's of type double) has to be a well formed program. So with Y being an int * the following must be well formed:

_Generic((Y), \
             double * :  test_double \
              ), \

并且由于int *不是double *,所以这里出现了问题.

And since an int * is not a double *, things break here.

我只是查看标准(实际上是N1570),却找不到实际上完全指定了此行为的任何东西.我想有人可能会报告这种情况下的缺陷,标准对此太含糊了.我正在尝试这样做.

I was just looking through the standard (N1570 actually) and could not find anything that actually specifies exactly this behavior, though. I guess one could report a defect in this case, the standard is too vague about this. I'm trying to do this now.

这篇关于C11 _通用用法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆