c++ 中extern C 及#ifdef __cplusplus的作用

浅析extern “C”的作用

 

        关于extern “C”的作用和意思,网上资料已经有很多了(我也参考了几篇),不过我还是觉得有必要自己总结一下,毕竟“好记性不如烂笔头”嘛~~

        到C标准函数库的头文件里看看,一般会经常看见有如下宏定义(除非你从来没有查看类似printf函数在头文件中的定义,就另当别论了:-()

#ifdef  __cplusplus
extern "C" {
#endif
…… (C函数声明)
#ifdef  __cplusplus
}
#endif
        简单来说,这个extern“C”用于C++代码调用C的函数(至于C代码如何调用C++函数,还是问问Google大神吧~)

        先撇开上述的extern “C”,看看C函数和C++函数的汇编代码,就知道在目标文件中,C函数名和C++函数名采用不同的命名规则。

        VS2010新建一个Windows Console工程,添加一个.c和.cpp文件,文件里的代码都一样,如下

void hello()
{
 
}
        为了使汇编文件的内容简单一些,这里函数体是空,而且没有引入任何头文件。VS2010默认不输出.asm文件,即汇编文件。在工程的配置中,让VS2010输出汇编文件,如下


        编译解决方案(或按“F7”),可以在工程目录的Debug文件夹下,找到对应的两个汇编文件,内容如下


        没有必要把这里全部的汇编代码看懂,只要明白在源代码中同一个hello函数,在翻译过来的.asm文件中,hello函数名的命名不一样就行了。

        很明显,如果C++代码要调用C函数,需要按照C函数编译后的函数名去调用这个函数。所以,extern “C”的作用就是告诉编译器,花括号“{}”中间的这些函数声明全部都是C函数。

        下面修改一下.c和.cpp文件的内容,如下

// C代码
#include <stdio.h>
 
void hello()
{
    printf("Hello, world!\n");
}
// C++代码
void hello();
 
int main(void)
{
    hello();
}
        这里要说明下,由于.c和.cpp文件在同一个工程下,所以简单起见,没有使用头文件引入hello函数,这里hello函数是全局的。运行工程发现出错如下


        这里?hello@@YAXXZ就是上面.cpp文件中hello函数编译后出现在对应的.asm文件中的。显然,编译器按照这个名称去找目标文件(.obj文件)中的hello是找不到的,因为.c文件编译后的.obj文件中,hello函数名被改成_hello。

        这时,把extern “C”加到.cpp文件中,如下

extern "C" {
    void hello();
};
 
int main(void)
{
    hello();
}
        果然,程序可以通过编译运行了。到这里,基本上extern ”C”的作用都讲清楚了。至于__cplusplus宏,用于判断当前源文件是不是C++源文件,因为extern “C”这种写法在C源文件中不允许的,如下,所以使用__cplusplus宏可以避免extern “C”被引入到C源文件中。即

(1)当前源文件是C++,则__cplusplus宏生效,extern “C”以及花括号“{}”的内容被引入C++源代码中;

(2)当前源文件是C,则__cplusplus宏无效,extern “C”以及花括号“{}”的内容不被引入C源代码中。

 

参考资料:

1、http://tech.163.com/06/0118/09/27O66HCC0009159Q.html

2、http://hi.baidu.com/mailrabbit/item/d53990f26265111aa7298876

3、http://blog.csdn.net/norains/article/details/1958052

4、http://luleimi.blog.163.com/blog/static/175219645201281244439794/
————————————————

原文链接:https://blog.csdn.net/DayDreamingBoy/article/details/8775409

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/380965.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

对多个WCF服务进行统一的连接测试

先看下面的代码&#xff1a;代码代码 BasicHttpBinding myBinding newBasicHttpBinding(); EndpointAddress myEndpoint newEndpointAddress(endAddress); ChannelFactory<IMyService>myChannelFactory newChannelFactory<IMyService>(myBinding,my…

宜昌宝塔河项目_宜昌城区首个垃圾分类定时定点投放点启用 厨余垃圾破袋投放...

伍家岗区宝联社区黄龙小区的垃圾分类定时定点投放点启用。(市环境卫生管理处供图)(记者郑璐、通讯员陈赞)1月1日&#xff0c;宜昌城区首个垃圾分类定时定点投放点在伍家岗区宝塔河街办宝联社区黄龙小区正式启用。该投放点每天开放5小时&#xff0c;上午7&#xff1a;00-9:30&am…

eclipseweb开发response和request接收发送数据乱码问题

第一种&#xff1a;request接收到的数据出现乱码&#xff1a; 在request接收数据前面设置如下代码 requset.setCharacterEncoding("UTF-8);reponse往页面写中文出现乱码&#xff1a; 在要往页面输入内容前面设置&#xff1a; response.setContentType("text/html;…

C++函数名的修饰规则

我们知道在C中有函数重载这样一个东西&#xff0c;当我们定义了几个功能类似且函数名是一样的函数的时候&#xff0c;只要它的参数列表不同&#xff0c;编译是可以通过的&#xff0c;但是在C中是不可以的。 double add(double a, double b) { return a b; } int add(int …

装配图位置偏转怎么调整_物理微课|匀变速直线运动、电容器动态分析及磁偏转技巧、方法、模型...

匀变速直线运动三大推论是什么&#xff1f;如何利用它们快速解题&#xff1f;电容器动态分析的重点是什么&#xff1f;磁偏转问题有什么严谨好用的技巧和方法&#xff1f;物理侯老师为您详细解答以上问题。高一匀变速直线运动三大推论 匀变速直线运动是我们高中学的第一个变速…

Cooki模拟登陆(人人网)

我们在爬取网上一些数据时&#xff0c;必须登陆才能爬取到数据&#xff0c;这是我们就需要Cookie了&#xff0c;Cookie简单说就是服务器返回给我们的一些数据&#xff0c;保存到客户端&#xff0c;下次登陆时&#xff0c;服务器会识别这些数据&#xff0c;可以返回我们上次的数…

静态变量与动态变量

0.静态存储与动态存储 1&#xff09;静态存储变量通常是在变量定义时就分定存储单元并一直保持不变&#xff0c;直至整个程序结束。静态变量&#xff0c;全局动态变量都是静态存储 2&#xff09;动态存储变量是在程序执行过程中&#xff0c;使用它时才分配存储单元&#xff0c…

基本图形怎么改字体_PPT做得慢怎么办?掌握这6个技巧,你也能快速做出精美的PPT...

相信很多人做PPT的速度都比较慢&#xff0c;从新建一个空白PPT开始&#xff0c;再到排版设计&#xff0c;需要耗费大量的时间&#xff0c;下面就来教你这6个技巧&#xff0c;你也能快速做出精美的PPT。01.一键禁止动画最近&#xff0c;有很多小伙伴向我求助&#xff0c;问我怎样…

js eval()函数

JS eval()函数转自&#xff1a;http://www.86822.com/code/zw.asp?id614 eval()函数 JavaScript有许多小窍门来使编程更加容易。 其中之一就是eval()函数&#xff0c;这个函数可以把一个字符串当作一个JavaScript表达式一样去执行它。 举个小例子&#xff1a;…

vs 2019编写汇编并运行调试

前言 我是上学期学的汇编&#xff0c;因为有vs又不想用课上教的麻烦的dosbox以及masm32&#xff0c;但是一直没找到高亮插件和能调试的&#xff08;难在运行不了而找不到答案上&#xff0c;出现的错误在最后放出&#xff0c;还请先达们不吝指点&#xff09;汇编代码所以放弃了。…

三菱880彩铅和uni的区别_孟祥雷丨清华美院毕业,彩铅界的“冷军”(附彩铅教程哦!)...

今天要分享的是妥妥的一个高冷帅气、又有才华的艺术家&#xff0c;毕业于清华大学美术学院。有20多年的绘画经验&#xff0c;设计、绘画等艺术多面手&#xff0c;彩铅是他最出名的作品之一。人物篇(逆光)(麻花辫)用彩铅画肖像人物的人很多&#xff0c;但能把人物塑造得维妙维俏…

substring()分解字符串

substring解决了如何在指定位置将一个字符串划分为子串 单参数形式&#xff1a;返回从起始位置到结尾之间的子串**&#xff08;起始索引从0开始&#xff09;** public class SubStringReview {public static void main(String[] args) {String s "Java is great";…

ubuntu 16.04忘记登录密码的解决办法

1、开机长按shift&#xff0c;我这是按esc&#xff0c;出现如下界面&#xff0c;选中如下选项&#xff1a; 2、按回车键进入如下界面&#xff0c;然后选择有recovery mode的选项&#xff0c;注意&#xff1a;然后按e进入3的界面&#xff08;请不要使用enter键&#xff09; 推…

11g oracle xe启动_详解Oracle等待事件的分类、发现及优化

一、等待事件由来大家可能有些奇怪&#xff0c;为什么说等待事件&#xff0c;先谈到了指标体系。其实&#xff0c;正是因为指标体系的发展&#xff0c;才导致等待事件的引入。总结一下&#xff0c;Oracle的指标体系&#xff0c;大致经历了下面三个阶段&#xff1a;以命中率为主…

您可能不知道的 C++ 关键字

C 有些操作符&#xff0c;其实有对应的关键字&#xff08;目的是为了在没有这些字符的键盘也可以输入C程序) and &&and_eq &bitand &bitor |compl ~not !or ||or_eq |xor ^xor_eq ^not_eq !从可读性的角度看&#xff0c…

StringTokenizer将一个字符串分解为单词或者标记

原理&#xff1a;StringTokenizer方法实现了Iterator的设计模式&#xff0c;也直接实现了枚举接口&#xff0c;通常情况下StringTotkenizer对象根据欧洲语言的单词分割将对字符串分解为若干单词&#xff0c;例如&#xff1a; public class StringTokenizerReview {public stat…

Ubuntu14.04设置开机可以以root用户身份登录

ubuntu系统信息&#xff1a; 步骤&#xff1a; 1. 切换到root用户 2. 设置Root用户密码 3.进入到相应目录 cd /usr/share/lightdm/lightdm.conf.d/ 4.编辑 50-ubuntu.conf文件&#xff0c; 增加greeter-show-manual-logintrue 5.关机重启&#xff0c;在开机界面弹出如下图所示…

JSP数据库连接

JSP数据库连接 一、SQL Server 2000数据库的连接 驱动&#xff1a;String driverClass"com.microsoft.jdbc.sqlserver.SQLServerDriver"; 需要用到的包&#xff1a; msbase.jar , mssqlserver.jar, msutil.jar URL: String url"jdbc:microsoft:sqlserver://127…

hystrix 单独使用_Hystrix学习

学习主题&#xff1a;Hystrix解决灾难性雪崩效应-服务熔断-服务熔断处理熔断参数circuitBreaker.enabled的作用是什么&#xff1f;熔断参数circuitBreaker.requestVolumeThreshold的作用是什么&#xff1f;熔断参数circuitBreaker.sleepWindowInMiliseconds的作用是什么&#x…

Centos7搭建Ngrok

安装gcc和git&#xff08;下载ngrok源码&#xff09; yum install gcc -y yum install git -y yum install -y mercurial git bzr subversion golang golang-pkg-windows-amd64 golang-pkg-windows-386 yum update -y nss curl libcurl yum -y install gcc automake auto…