我找到了一个例子:
在main.c中
int main() {
cppsayhello("Hello from C to C++");
return 0;
}
在cppsayhello.cpp
#include<iostream>
#include"cppsayhello.h"
extern "C" void cppsayhello(char* str);
void cppsayhello(char *str) {
std::cout << str << std::endl;
}
有效! main.c
不包含任何内容,main.c
如何知道函数cppsayhello
的存在?有人会告诉我它是如何在幕后工作的。
(我现在正在开发一个嵌入式系统。底层是用C语言编写的,我想用c ++来构建顶级应用程序。但是用2种语言很难处理。)
答案 0 :(得分:2)
main.c由C编译器编译,允许隐式函数声明。当C编译器找到一个尚未声明的函数时,它假定它是holder.ImgArticlePhoto = view.FindViewById<ImageView> (Resource.Id.img_ArticlePhoto);
Koush.UrlImageViewHelper.SetUrlDrawable (holder.ImgArticlePhoto,item.Image);
,这意味着函数包含C中任意数量的任何参数。
C99和更新版本不允许隐式声明,并且代码不能使用符合C99的编译器进行编译。
答案 1 :(得分:1)
这表明您的C编译器早于1999标准,因为后来的C编译器将拒绝该main()
函数。
一般来说,对于较旧的C编译器,即使隐式声明的函数的使用与实际定义不匹配,您的C代码也会链接。结果是未定义的行为(尽管在实践中,代码通常仍然有效 - 未定义行为的一种可能表现是代码至少与某些编译器一起工作)。
它在幕后工作,因为C - 不像C ++ - 不支持函数重载。因此,任何名为cppsayhello()
的函数都将由编译器赋予相同的名称(在目标文件中),因此链接器可以匹配。因此,您可以将cppsayhello()
定义为具有任何返回类型,以及您希望的任何参数集 - 您的代码仍将编译和链接。但是,链接器必须只能看到一个定义(如果它遇到多个定义的任何东西,它会抱怨多重定义的符号 - 例如,链接两个目标文件,每个目标文件包含一些函数的定义)。
如果main()
函数可以看到函数的正确声明,那么您的代码将避免未定义的行为。
void cppsayhello(const char *);
int main()
{
cppsayhello("Hello from C to C++");
return 0;
}
如果它以任何与声明不一致的方式使用函数,那将阻止main()
函数编译。
答案 2 :(得分:0)
整个事情是未定义的行为,并且运气好。 幕后发生了一些事情,但你的编译器应该抱怨很多。
int
而不检查参数。 (这适用于C99以前的C语言.C99或更高版本会因此代码出错)extern "C"
你的C ++编译器创建了一个目标文件,其中包含一个具有C调用约定的函数,没有名称管理。 cppsayhello
,在main.c中找到所需的符号cppsayhello
。所以它将两者联系起来。显然他们有不同的签名但在你的情况下忽略返回的值并且参数是兼容的。但实际的运行时行为可能取决于体系结构和编译器。
简而言之:您的示例代码非常糟糕。