为什么结构体中的函数适用于 C 语言



如这个小脚本所示。

#include <stdio.h>
struct student{
short count;
void (*addCount)();
};
void student_addCount(struct student a){
a.count++;
}
int main(){
struct student student;
student.addCount = student_addCount;
student.count = 0;
student.addCount();
student.addCount();
student.addCount();
student.addCount();
student.addCount();
printf("%dn",student.count);
}

我在结构内添加了一个指向函数的指针,但我不知道为什么这会起作用,因为函数"addCount"没有接收任何参数,它实际上增加了指定的次数。

我正在使用GCC 6.3.0在不同的环境中编译此代码,例如 ideone.com,wandbox.org 和WSL中的编译器。

这是它与IDEe一起工作的证据。 https://ideone.com/Cam4xY

这不是结构内的函数,而是结构内的函数指针。

void (*addCount)();

addCount定义为指向函数的指针。该函数返回void并接受未指定数量的参数。

这就是空括号的意思。这是一个旧式的非原型函数声明。很少(如果有的话)有充分的理由使用非原型函数声明或定义。如果要指定函数不带参数,请使用(void)而不是()

student.addCount = student_addCount;

函数student_addCount采用struct student参数,但其类型仍与指针成员的类型兼容。像这样分配它基本上禁用了对呼叫的检查。这就是为什么旧式函数声明是一个坏主意的原因。

student.addCount();

这是通过函数指针进行的间接调用。 由于函数指针类型未指定预期多少参数,因此调用是合法的。因为实际被调用的函数需要一个类型struct student的参数,所以行为是未定义的。对于旧式函数声明,完全取决于您(程序员)来正确获取参数;编译器不会帮助你。

由于您获得的结果似乎是有效的,因此您期望传递的参数很可能恰好位于内存中的正确位置,也许在堆栈的顶部。调用该函数,它非常合理地假定您已经传递了正确的参数值。它在内存或寄存器中查找该参数,并找到...什么东西

下面是没有未定义行为的程序版本:

#include <stdio.h>
struct student{
short count;
void (*addCount)(struct student a);
};
void student_addCount(struct student a){
a.count++;
}
int main(void){
struct student student;
student.addCount = student_addCount;
student.count = 0;
student.addCount(student);
student.addCount(student);
student.addCount(student);
student.addCount(student);
student.addCount(student);
printf("%dn",student.count);
}

输出是0的 -- 因为递增的count是参数的成员,参数是本地对象。

这是一个可以满足您的需求的版本。它传递指向结构的指针,因此原始struct student对象的count成员按函数递增。输出为5

#include <stdio.h>
struct student{
short count;
void (*addCount)(struct student *a);
};
void student_addCount(struct student *a){
a->count++;
}
int main(void){
struct student student;
student.addCount = student_addCount;
student.count = 0;
student.addCount(&student);
student.addCount(&student);
student.addCount(&student);
student.addCount(&student);
student.addCount(&student);
printf("%dn",student.count);
}

相关内容

  • 没有找到相关文章

最新更新