Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.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_Function_Struct - Fatal编程技术网

C-结构内部的函数

C-结构内部的函数,c,function,struct,C,Function,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 cli

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

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();
}

哪种方法正确?

< p>这只会在C++中工作。结构中的函数不是C的特性

您的客户机也是如此;呼叫这是一个成员函数的调用,它是面向对象的编程,即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);

}

这不能直接完成,但您可以使用函数指针并显式传递“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以这种方式实现,因为您也可以只调用外部函数并传递实例。

正如其他人所指出的,直接在结构中嵌入函数指针通常是为了特殊目的而保留的,比如回调函数

您可能想要的是更像虚拟方法表的东西

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); }
现在,添加更多操作不会改变
客户机\u t
结构的大小。现在,这种灵活性只有在您需要定义多种类型的客户机,或者希望您的
客户机\u t
界面的用户能够增强操作的行为时才有用

这种结构确实出现在实际代码中。OpenSSL BIO层看起来与此类似,UNIX设备驱动程序接口也有类似的层。

这个怎么样

#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;
} 
#包括
typedef结构hello{
int(*someFunction)();
}你好,;
int foo(){
返回0;
}
你好你好{
结构hello aHello;
aHello.someFunction=&foo;
返回阿赫洛;
}
int main()
{
结构hello aHello=hello();
printf(“打印hello:%d\n”,aHello.someFunction());
返回0;
} 

您正在尝试根据结构对代码进行分组。 C分组是按文件进行的。 您将所有函数和内部变量放在标题或 从c源文件编译的头文件和对象“.o”文件

没有必要从头开始重新设计面向对象 对于不是面向对象语言的C程序

我以前见过这个。 这是一件奇怪的事情。编码人员,其中一些人,对将他们想要更改的对象传递到函数来更改它有一种厌恶,即使这是这样做的标准方式

我责怪C++,因为它隐藏了类对象总是成员函数中的第一个参数的事实,但是它是隐藏的。因此看起来它没有将对象传递到函数中,即使它是

Client.addClient(Client& c); // addClient first parameter is actually 
                             // "this", a pointer to the Client object.
C语言很灵活,可以通过引用来传递信息

C函数通常只返回一个状态字节或int,而这通常被忽略。 在您的情况下,适当的形式可能是

 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中,您可以将结构指针作为函数参数传递给函数。 它称为通过引用传递

如果修改该指针内的某些内容,其他内容将更新为。 试着这样做:

typedef结构客户端,*pno;
结构客户端
{
pid_t pid;
字符密码[TAM_MAX];//->50个字符
pno next;
};
pno添加客户端(客户端*client)
{
/*这将更改原始客户端值*/
client.password=“secret”;
}
int main()
{
客户(t客户),;
//代码。。
AddClient(&client);
}

在C中的结构中不能有函数;你可以试着用函数指针大致模拟一下。函数指针是可以接受的替代品吗?这是uni项目,我必须使用C。有什么方法可以在C中完成我想要的吗?只需将该函数移到结构之外,并使其接受指向实例的指针。如果没有一点复杂的魔力(参见另一个答案),client.AddClient()就不可能了。X11 API就是这样做的。请参阅。Windows API下的代码中充满了这一点。从技术上讲,“窗口类”是一个具有两个回调函数指针和开放端的结构(对于注册时可以提供的“窗口类特定数据”),遵循这些步骤,但当我执行struct.function=newFunction时,编译器打印:错误:预期为“=”,“,”,“;”,”asm“或”attribute“before.”标记当您需要一个具有读取功能和写入功能的公共目标(如硬盘驱动器)时,此标记也很有用,但从一种类型的硬盘驱动器到下一种类型,如果在运行时选择了实际实现,则它可以为您带来很多好处。如果只有一个静态函数,则每次调用函数时都需要在该函数中重新选择,如果使用函数指针,则选择只发生一次。选择甚至可以在结构的整个生命周期中发生变化。类似JavaScrip的“一点点”解决方案这种方法有其优点和缺点。仅仅因为它一直是这样做的,指的是非面向对象(
do(object,subject)
)和面向对象(
subject.do(object)
)的函数排列策略,并不意味着我们应该停止尝试。我完全认为有必要指出,这不是C编写的历史方式,C也不需要这样编写(许多语言也是如此,尤其是程序、函数或逻辑范式),但我不认为我们需要积极阻止这种模式。它也有一些好处。没有通过引用传递是C。您传递的是指针的副本,指针的引用是相同的,但是指针本身没有。谢谢您的更正。我已经读了教程的要点。这和我上面写的不同吗?pno指的是什么?请记住,这是来自OP的Linux。我对这种代码风格印象深刻。但我不知道为什么会出现分段错误我不明白
AddClient
是否是递归的?威尔c
 err = addClient( container_t  cnt, client_t c);
 if ( err != 0 )
   { fprintf(stderr, "could not add client (%d) \n", err );