C# C:函数指针与C的委托比较不安全的示例#

C# C:函数指针与C的委托比较不安全的示例#,c#,c,delegates,function-pointers,C#,C,Delegates,Function Pointers,当我学习C#的委托时,我的书上说委托与C中的函数指针相同,但更安全。在我读了这一行之后,我想:啊,所以C编译器不会检查函数指针指向的原型。我完全错了 int add(int a, int b){ return a + b; } float add_f(float a, float b){ return a + b; } int (*f)(int,int); f = add; // no compile-error f = add_f; //compile-error 那么,请告诉我为什么,并

当我学习C#的委托时,我的书上说委托与C中的函数指针相同,但更安全。在我读了这一行之后,我想:啊,所以C编译器不会检查函数指针指向的原型。我完全错了

int add(int a, int b){ return a + b; }
float add_f(float a, float b){ return a + b; }

int (*f)(int,int);
f = add; // no compile-error
f = add_f; //compile-error
那么,请告诉我为什么,并给我一些例子来证明C函数指针与C#中的委托相比是不安全的


在C++中,函数指针是类型安全的。你必须做一些非常愚蠢的事情来打破它们(通常包括演员、工会、
memcpy
,或类似的事情;这不可能是偶然发生的)

然而,在C语言中,函数类型并没有那么严格。您可以这样做:

int add(int a, int b){ return a + b; }
int add_f(float a, float b){ return a + b; }

int (*f)(); // empty argument list does NOT mean zero arguments.
            // for zero arguments, say int (*)(void)
f = &add;
f = &add_f;


有人问我一个极其愚蠢的例子

#包括
intadd(inta,intb){返回a+b;}
int add_f(float a,float b){返回a+b;}
联合{
整数(*f1)(整数,整数);
int(*f2)(浮动,浮动);
}计划生育;
内部主(空)
{
fp.f1=&add;

STD::C++中的CUT< P>,函数指针是类型安全的。你必须做一些非常愚蠢的事情来打破它们(一般涉及铸造、联合、<代码> MeMCPY <代码>或类似;它不会偶然发生)。 但是,在C中,函数类型几乎没有那么严格。您可以这样做:

int add(int a, int b){ return a + b; }
int add_f(float a, float b){ return a + b; }

int (*f)(); // empty argument list does NOT mean zero arguments.
            // for zero arguments, say int (*)(void)
f = &add;
f = &add_f;


有人问我一个极其愚蠢的例子

#包括
intadd(inta,intb){返回a+b;}
int add_f(float a,float b){返回a+b;}
联合{
整数(*f1)(整数,整数);
int(*f2)(浮动,浮动);
}计划生育;
内部主(空)
{
fp.f1=&add;

std::cout你不应该把每本书都说的话当作它的表面价值:C的函数指针和C#的委托之间的相似性是相当肤浅的。将它们的特性与特性进行比较会产生一系列的差异,而“安全性”远远不是最重要的


使用函数指针模拟C#委托的最大安全问题是函数指针所操作的数据的所有权。回想一下,委托并不局限于静态函数:您可以从成员函数生成委托,在这种情况下,对象成为“嵌入的”在委托中。C中没有类似的功能:为了“绑定”,您需要做大量的工作指向一段数据的函数指针。如果数据在以后某个时候变得不可用,并且函数试图使用该数据,则可能会触发崩溃。但这一差异是垃圾收集与手动管理内存环境的一个属性。

你不应该把每本书所说的作为其表面价值:f和f之间的相似性C的函数指针和C#的委托是相当肤浅的。比较它们的不同特性会产生一系列不同之处,而“安全性”远远不是最重要的


使用函数指针模拟C#委托的最大安全问题是函数指针所操作的数据的所有权。回想一下,委托并不局限于静态函数:您可以从成员函数生成委托,在这种情况下,对象成为“嵌入的”在委托中。C中没有类似的功能:为了“绑定”,您需要做大量的工作指向一段数据的函数指针。如果数据在以后某个时间变得不可用,并且函数尝试使用该数据,则可能会触发崩溃。但这一差异是垃圾收集与手动管理内存环境的一个属性。

Oh.awesome!:D 1)您能给出更多关于
memcpy
和某些类型o的示例吗“愚蠢的铸造。谢谢:”HQT:你也知道C中的那些工作,所以它们不是C++函数指针的例子,比C代表的安全性要小,对吧?@本找不到对“代码> MARHALL的引用”。,但由于封送处理类的全部要点是使用C语言规则之外的非托管代码,我认为这不是C不安全的一个很好的例子。这就像说Java不安全,因为您可以调用会占用整个内存空间的C代码。@Voo:对不起,这是
Marshal.Copy
和/或
Buffer.BlockCop是的,它绕过类型检查器,这与组合代表很愚蠢。这就是问题所在。C++中的强制转换、联合和代码> MycPy < /Cuff>也是如此;在函数指针上使用这些函数是疯狂的。(函数指针强制转换所需的一个位置是
GetProcAddress
/
dlsym
,但是p/invoke也会很高兴地创建一个错误类型的委托,如果签名错误的话)很好的帖子和很好的通信:)哦!太棒了!(D 1)你能给出更多关于“代码> MycPy < /Cube >和一些愚蠢的类型的例子吗?”谢谢::HQT:你也知道C中的那些工作,所以它们不是C++函数指针的例子,比C代表的安全性要小,对吧?@本找不到对“代码> MSEHALL的引用。(可能是指复制品或其他东西),但由于封送处理类的全部要点是使用C语言规则之外的非托管代码,我认为这不是C不安全的一个很好的例子。这就像说Java不安全,因为您可以调用会占用整个内存空间的C代码。@Voo:对不起,这是
Marshal.Copy
和/或
Buffer.BlockCop是的,它绕过类型检查器,这与组合代表很愚蠢。这就是问题所在。C++中的强制转换、联合和代码> MycPy < /Cuff>也是如此;在函数指针上使用这些函数是疯狂的。(函数指针强制转换所需的一个位置是
GetProcAddress
/
dlsym
,但是p/invoke也会很高兴地创建一个错误类型的委托,如果签名错误的话)很好的帖子和很好的通信:)