Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
函数重载不适用于c中的名称空间(结构)_C - Fatal编程技术网

函数重载不适用于c中的名称空间(结构)

函数重载不适用于c中的名称空间(结构),c,C,我在lib.h中有: #pragma once #include <stdio.h> #include <stdlib.h> typedef struct LIB { int (*a1)(int); int (*a2)(int); } lib; int a1(int a, int b); int a2(int a, double b); #define a0(X, Y) _Generic((X),\ int: _Generic((Y),\

我在lib.h中有:

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

typedef struct LIB {
  int (*a1)(int);
  int (*a2)(int);
} lib;

int a1(int a, int b);
int a2(int a, double b);

#define a0(X, Y) _Generic((X),\
    int:   _Generic((Y),\
        int: a1,\
        double: a2\
    )\
)(X, Y)

lib* getLib(void);
总而言之,c:

#include "lib.h"

int main() {
  lib* l = getLib();
  int v = l->a0(1, 2.4); // error
}
错误:

error: expected identifier
note: expanded from macro 'a0'
没有定义,如果将a0更改为a2,则可以工作。 如何重载命名空间结构中的函数?为什么我在这里有错误

upd:加上“void”(谢谢评论),我在主要部分(第一个答案)有一个错误,这只是问题中的一个错误

否定答案 您的类型
lib
没有成员
v
。问题的原始版本包含以下代码:

int l->v = a0(1, 2.4); // error
您不能使用
int l->v
来创建…好吧,不清楚您希望它创建什么,但是即使有一个元素
l->v
,您也无法按照您的尝试将其类型定义为
int

到目前为止,问题实际上与泛型选择操作符
\u generic
(参见C11)无关。这只是你在追逐的一条红鲱鱼

您可以尝试使用:

int v = a0(1, 2.4);
然而,您随后会遇到问题,因为
a0
的结果是…嗯,最初我说它是一个函数指针,但它不是;代码尝试调用该函数。但是您不能通过
\u Generic
选择来选择要访问的结构的哪个成员,就像您不能编写
l->(a>1?a1:a2)
一样

我相信你需要重新思考一下。你似乎走错了方向。不过,我不能做更多的事情让你们回到正轨上,因为我不清楚你们想去哪里

你提到C++命名空间。如果要在C中模拟名称空间,可能需要使用宏和令牌连接。在C中重载函数并不是一件小事。试图从结构成员中使用重载基本上是行不通的,当然不能使用这种技术

我在回答中提到的——如果你想使用C++的特性,使用C++ +< /P> 肯定的回答 这是一个有效的机制——但它需要一个(稍微)不同的宏,等等。我将三个文件合并为一个,但是您可以轻松地将代码重新分离为三个文件。您将删除一些注释,但不是全部注释

// File: lib.h
// #pragma once
#ifndef LIB_H
#define LIB_H

typedef struct LIB
{
    int (*a1)(int, int);
    int (*a2)(int, double);
} lib;

int a1(int a, int b);
int a2(int a, double b);

#define a0(lib, X, Y) (_Generic((X), \
                          int :   _Generic((Y), \
                                           int : (lib)->a1, \
                                           double : (lib)->a2 \
                                           ) \
                          )(X, Y))

extern lib *getLib(void);

#endif /* LIB_H */

// File: lib.c
// #include "lib.h"
#include <stdlib.h>

int a1(int a, int b)
{
    return a % b;
}

int a2(int a, double b)
{
    return a + b;
}

lib *getLib(void)
{
    lib *ret = (lib *)malloc(sizeof(lib));

    ret->a1 = a1;
    ret->a2 = a2;

    return ret;
}

// File: main.c
// #include "lib.h"
#include <stdio.h>

int main(void)
{
    lib *l = getLib();
    // int v = l->a0(1, 2.4); // error

    int v = a0(l, 1, 2.4);
    printf("v = %d\n", v);
    int w = a0(l, 24, 5);
    printf("w = %d\n", w);
    return 0;
}
讨论:

泛型选择“返回”的值必须是
lib
结构的元素。结构中的函数原型将更新以反映两个参数的存在,第二个参数的类型不同

隐藏通用选择运算符的
a0
宏现在通过
lib*
调用;这些操作根据参数类型从结构中选择不同的成员。主要区别在于成员访问嵌入在宏中,而不是部分在宏内部和外部

main.c
中的测试代码显示可以调用这两个函数。请注意,没有涉及铸造,结果是正确的(1+2==3;24%5==4)


我并不是说这是用C编写代码的好方法。但是,这样做似乎是可行的。

基本问题是,表达式中
->
标记后面的东西必须是标识符,即结构中字段的名称。它不能是“计算”字段名称的表达式;连写这样的东西都没有办法


另一方面,a
\u Generic
是一个表达式——它只能在C需要表达式的地方使用,

这与您所问的内容无关,但是……为什么您没有在标题中定义
getLib()
的原型呢?您提供的是一个非原型声明——如果函数不带任何参数,则需要声明
lib*getLib(void)因为这是一个原型。为了保持一致性,您应该将函数定义为
lib*getLib(void){…}
。编写的函数定义也不提供原型。我建议不要使用<代码>泛型<代码>。在那种方式下,我只是尝试在C中做一些名称空间(C++),但只存在结构,我想在这里做一个函数重载,我尝试做这个,如果你想要C++特性,使用C++。C不是C++;使用C好像是C++是不明智的。大学程序并不像发展快的语言——不幸的是,我必须使用。C@THND-注意“肯定回答”下的(主要)更新。
// File: lib.h
// #pragma once
#ifndef LIB_H
#define LIB_H

typedef struct LIB
{
    int (*a1)(int, int);
    int (*a2)(int, double);
} lib;

int a1(int a, int b);
int a2(int a, double b);

#define a0(lib, X, Y) (_Generic((X), \
                          int :   _Generic((Y), \
                                           int : (lib)->a1, \
                                           double : (lib)->a2 \
                                           ) \
                          )(X, Y))

extern lib *getLib(void);

#endif /* LIB_H */

// File: lib.c
// #include "lib.h"
#include <stdlib.h>

int a1(int a, int b)
{
    return a % b;
}

int a2(int a, double b)
{
    return a + b;
}

lib *getLib(void)
{
    lib *ret = (lib *)malloc(sizeof(lib));

    ret->a1 = a1;
    ret->a2 = a2;

    return ret;
}

// File: main.c
// #include "lib.h"
#include <stdio.h>

int main(void)
{
    lib *l = getLib();
    // int v = l->a0(1, 2.4); // error

    int v = a0(l, 1, 2.4);
    printf("v = %d\n", v);
    int w = a0(l, 24, 5);
    printf("w = %d\n", w);
    return 0;
}
v = 3
w = 4