C -结构内的函数

vx6bjr1n  于 2023-03-07  发布在  其他
关注(0)|答案(7)|浏览(113)

我试图在struct中分配一个函数,到目前为止,我有以下代码:

typedef struct client_t client_t, *pno;
struct client_t
{
    pid_t pid;
    char password[TAM_MAX]; // -> 50 chars
    pno next;
    
    pno AddClient() 

    {
        /* code */
    }
};

int main()
{
    client_t client;

    // code ..

    client.AddClient();
}
**Error**: *client.h:24:2: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘{’ token.*

做这件事的正确方法是什么?

c3frrgcw

c3frrgcw1#

这不能直接完成,但可以使用函数指针并显式传递“this”参数来模拟相同的操作:

typedef struct client_t client_t, *pno;
struct client_t
{
    pid_t pid;
    char password[TAM_MAX]; // -> 50 chars
    pno next;

    pno (*AddClient)(client_t *); 
};

pno client_t_AddClient(client_t *self) { /* code */ }

int main()
{

    client_t client;
    client.AddClient = client_t_AddClient; // probably really done in some init fn

    //code ..

    client.AddClient(&client);

}

然而,事实证明,这样做并不会给你带来太多的好处,因此,你不会看到很多C API以这种风格实现,因为你可能只是调用你的外部函数并传递示例。

r8uurelv

r8uurelv2#

正如其他人所指出的,直接在结构中嵌入函数指针通常是为特殊目的保留的,比如回调函数。
您可能需要更像虚方法表的东西。

typedef struct client_ops_t client_ops_t;
typedef struct client_t client_t, *pno;

struct client_t {
    /* ... */
    client_ops_t *ops;
};

struct client_ops_t {
    pno (*AddClient)(client_t *);
    pno (*RemoveClient)(client_t *);
};

pno AddClient (client_t *client) { return client->ops->AddClient(client); }
pno RemoveClient (client_t *client) { return client->ops->RemoveClient(client); }

现在,添加更多的操作并不会改变client_t结构的大小,这种灵活性只有在需要定义多种客户端,或者希望client_t接口的用户能够增加操作的行为时才有用。
这种结构确实出现在真实的代码中,OpenSSL BIO层看起来与此类似,UNIX设备驱动程序接口也有一个类似的层。

yvgpqqbh

yvgpqqbh3#

这个怎么样?

#include <stdio.h>

typedef struct hello {
    int (*someFunction)();
} hello;

int foo() {
    return 0;
}

hello Hello() {
    struct hello aHello;
    aHello.someFunction = &foo;
    return aHello;
}

int main()
{
    struct hello aHello = Hello();
    printf("Print hello: %d\n", aHello.someFunction());

    return 0;
}
vi4fp9gy

vi4fp9gy4#

这只在C中有效。结构体中的函数不是C的特性。
同样的道理也适用于您的客户端。AddClient();call...这是对成员函数的调用,这是面向对象的编程,即C

将源代码转换为.cpp文件,并确保相应地进行编译。
如果你需要坚持使用C语言,下面的代码(在某种程度上)是等价的:

typedef struct client_t client_t, *pno;
struct client_t
{
        pid_t pid;
        char password[TAM_MAX]; // -> 50 chars
        pno next;

};

pno AddClient(pno *pclient) 
{
    /* code */
}

int main()
{

    client_t client;

    //code ..

    AddClient(client);

}
w51jfk4q

w51jfk4q5#

你试图根据struct对代码进行分组。C是按文件分组的。你把所有的函数和内部变量放在一个头文件中,或者把一个头文件和一个从c源文件编译来的对象“.o”文件中。
对于C程序来说,没有必要从头开始重新发明面向对象,因为它不是一种面向对象的语言。
我以前见过这种情况,这是一件很奇怪的事情,有些程序员讨厌把他们想改变的对象传递给函数来改变它,尽管这是标准的方法。
我责怪C++,因为它隐藏了类对象总是成员函数的第一个参数的事实,但是它是隐藏的,所以看起来它没有把对象传递给函数,尽管它是。

Client.addClient(Client& c); // addClient first parameter is actually 
                             // "this", a pointer to the Client object.

C语言很灵活,可以通过引用来获取传递的东西。
一个C函数通常只返回一个状态字节或int,这通常被忽略。在你的例子中,一个合适的形式可能是

/* add client to struct, return 0 on success */
 err = addClient( container_t  cnt, client_t c);
 if ( err != 0 )
   { 
      fprintf(stderr, "could not add client (%d) \n", err ); 
   }

addClient将位于Client. h或Client. c中

aelbi1ox

aelbi1ox6#

假设您有以下结构:

struct Object {
    int field;
}

在C中,没有好的方法来编写object.Add(1)并使Add使用/更改object的字段。
a)放弃写object.Add(1)的愿望,写习惯的C代码代替。试图找到一种方法来写object.Add(1)在C中使用一些技巧只会使代码更复杂,更容易出现错误,是不值得的。
在C语言中,等效的方法是让一个单独的函数接受一个指向对象的指针:

void Add(struct Object *object, int amount) {
    object->field += amount;
}

并调用此函数,如下所示:

struct Object object;
Add(&object, 1);

B)使用另一种编程语言。例如,在C++中,您可以定义一个方法:

struct Object {
    int field;
    void Add(int amount) {
        field += amount;
    }
}

并在代码中使用它:

Object object;
object.add(1);

C编译器会让它代表你工作,事实上,只要不涉及继承,C代码就会等价于(a)中提到的函数定义及其调用。

bxfogqkk

bxfogqkk7#

你可以把结构指针作为函数参数传递给函数,这叫做按引用传递.
如果您修改了该指针内的某些内容,则其他内容将更新为。请尝试如下操作:

typedef struct client_t client_t, *pno;
struct client_t
{
        pid_t pid;
        char password[TAM_MAX]; // -> 50 chars
        pno next;
};

pno AddClient(client_t *client)
{
        /* this will change the original client value */
        client.password = "secret";
}

int main()
{
    client_t client;

    //code ..

    AddClient(&client);
}

相关问题