在 C# CLR 中学习 C++ 之了解 extern
一:背景
在 CLR 源码中有很多的 extern 和 extern "C" 这样的关键词,比如下面这些代码:
extern size_t gc_global_mechanisms[MAX_GLOBAL_GC_MECHANISMS_COUNT];
extern DWORD g_dwHandles;
// The single GC heap instance, shared with the VM.
extern IGCHeapInternal* g_theGCHeap;
extern PTR_VOID GetUnwindDataBlob(TADDR moduleBase, PTR_RUNTIME_FUNCTION pRuntimeFunction, /* out */ SIZE_T * pSize);
extern "C" uint32_t* g_gc_card_table;
extern "C" uint8_t* g_gc_lowest_address;
extern "C"
{
uint8_t *g_gc_sw_ww_table = nullptr;
bool g_gc_sw_ww_enabled_for_gc_heap = false;
}
那这些都是什么意思呢? 为了更好的学习 CLR,这些还是要简单了解一下的。
一:extern
1. 变量定义和变量引用
在 C# 中并没有听说过有 extern 这种概念,其实变量可以有两种方式存在。
变量定义
变量引用
变量定义概念很简单,定义就得给它分配内存空间,比如下面这样:
#include <iostream>
#include <Windows.h>
int k = 10;
const char* ch = "abcde";
int main()
{
printf("ch=%d", strlen(ch));
}
接下来看下 变量引用,它其实和 文件引用 以及 C# 的 using 概念相似,即把其他文件中的变量引入到本文件,目的就是为了使用,比如在 Arts 文件下定义了一个 page.cpp 文件,截图如下:

为了能够在 ConsoleApplication3.cpp 中使用 int i ,那怎么办呢? 这时候就需要用 extern 引入了。

因为 VisualStudio 可以帮我们自动链接,所以这里就不需要 #include "page.cpp" 导入,接下来把程序跑起来,就可以观察到程序的结果。

如果不用 extern 导入的话,就会出现编译错误,说 n 是未定义的。

还有一点要注意 extern 是对外部变量的一个引用,它不会生成任何汇编代码。
2. extern "C"
要理解这个关键词,首先要明白 方法符号 的概念,因为 C 和 C++ 在给方法生成符号的逻辑是不一样的,比如同样的一个 fly 函数。
#include <stdio.h>
void fly() {
printf("hello world");
}
int main()
{
}
在 C 中生成的函数名还是 fly 字样。

可 C++ 不这么认为,它会对 fly 函数名重新编排,比如下面的 ?fly@@YAXXZ。

如果你在 C++ 中混用 C 的话,这时候就有理念冲突,那在C++中让某些函数名还是原样生成有办法吗?当然可以了,这就需要使用 extern "C" ,参考如下代码:
// page.cpp
#include <stdio.h>
extern "C"
{
void fly() {
printf("hello");
}
}
void fly2() {
printf("hello");
}
然后可以在 ConsoleApplication.cpp 中引入进来。
// ConsoleApplication.cpp
#include <iostream>
extern "C" void fly();
extern void fly2();
int main()
{
fly();
fly2();
return 0;
}

好了,本篇就简单说这么多吧,相信再回头看 CLR 中的那些 extern 关键词,你会有一些新的理解。
在 C# CLR 中学习 C++ 之了解 extern的更多相关文章
- 在 C# CLR 中学习 C++ 之了解 namespace
一:背景 相信大家在分析 dump 时,经常会看到 WKS 和 SRV 这样的字眼,如下代码所示: 00007ffa`778a07b8 coreclr!WKS::gc_heap::segment_st ...
- [C#] 类型学习笔记一:CLR中的类型,装箱和拆箱
在学习.NET的时候,因为一些疑问,让我打算把.NET的类型篇做一个总结.总结以三篇博文的形式呈现. 这篇博文,作为三篇博文的第一篇,主要探讨了.NET Framework中的基本类型,以及这些类型一 ...
- CLR中的程序集加载
CLR中的程序集加载 本次来讨论一下基于.net平台的CLR中的程序集加载的机制: [注:由于.net已经开源,可利用vs2015查看c#源码的具体实现] 在运行时,JIT编译器利用程序集的TypeR ...
- 从bug中学习怎么写代码
博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:从bug中学习怎么写代码.
- 从mina中学习超时程序编写
从mina中学习超时程序编写 在很多情况下,程序需要使用计时器定,在指定的时间内检查连接过期.例如,要实现一个mqtt服务,为了保证QOS,在服务端发送消息后,需要等待客户端的ack,确保客户端接收到 ...
- CLR中的垃圾回收机制
CLR中采用代(generation)来作为其垃圾回收的一种机制,其唯一的目的是提升程序的性能.基予代的垃圾回收器有以下假设: ·对象越新,其生存周期越短. ·对象越老,其生存周期越长. ·回收堆的一 ...
- 在Object-C中学习数据结构与算法之排序算法
笔者在学习数据结构与算法时,尝试着将排序算法以动画的形式呈现出来更加方便理解记忆,本文配合Demo 在Object-C中学习数据结构与算法之排序算法阅读更佳. 目录 选择排序 冒泡排序 插入排序 快速 ...
- 贝叶斯网(2)Netica:从数据中学习CPT
1. 离散节点 在官方Tutorial中是有详细的案例的,就是B篇3.3节,你可以动手把天气预报这个实现一下: http://www.norsys.com/tutorials/netica/secB/ ...
- 【工作中学习1】两个设计模式:Singleton(单例)和 Adapter(适配器)
好久没有写自己的学习小博客,罪过罪过..最近本菜鸟在项目中接触到经常用到的设计模式,首先是Singleton(单例),这个相信大家都会用到很多,所以自己用代码实现一下,有助于自己学习理解,如有不对,请 ...
随机推荐
- 重学ES系列之函数优化
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 面试突击60:什么情况会导致 MySQL 索引失效?
为了验证 MySQL 中哪些情况下会导致索引失效,我们可以借助 explain 执行计划来分析索引失效的具体场景. explain 使用如下,只需要在查询的 SQL 前面添加上 explain 关键字 ...
- Numpy的ndarray数组基础
NumPy 最重要的一个特点是其 N 维数组对象 ndarray,它是一系列同类型数据的集合,以 0 下标为开始进行集合中元素的索引. ndarray 对象是用于存放同类型元素的多维数组. 1.数组的 ...
- 分布式事务(Seata) 四大模式详解
前言 在上一节中我们讲解了,关于分布式事务和seata的基本介绍和使用,感兴趣的小伙伴可以回顾一下<别再说你不知道分布式事务了!> 最后小农也说了,下期会带给大家关于Seata中关于sea ...
- 一张图进阶 RocketMQ - 消息发送
前 言 三此君看了好几本书,看了很多遍源码整理的 一张图进阶 RocketMQ 图片链接,关于 RocketMQ 你只需要记住这张图!觉得不错的话,记得点赞关注哦. [重要]视频在 B 站同步更新,欢 ...
- final关键字用于修饰局部变量和修饰成员变量
修饰变量 1. 局部变量--基本类型 基本类型的局部变量,被fifinal修饰后,只能赋值一次,不能再更改.代码如下: public class FinalDemo1 { public static ...
- 基于 Hexo 从零开始搭建个人博客(二)
阅读本篇前,请先配置好相应的环境,请仔细阅读教程 基于 Hexo 从零开始搭建个人博客(一). 原文链接:基于 Hexo 从零开始搭建个人博客(二) 前言 博客搭建过程遇到任何问题,优先在本页面搜索, ...
- 关于(Java)方法的再认识
1.方法的调用(图中两个方法在一个包中) 2.静态与非静态 两个非静态可以调用 但是静态不可以同时调用非静态 package com.oop;public class Way02 { public s ...
- NOI / 2.1基本算法之枚举题解-1(3861字)制作不易
目录 1.15 Counterfeit Dollarhttp://noi.openjudge.cn/ch0201/15/ 2.1749 数字方格
- 字节输出流的续写和换行和字节输入流InputStream类&FileInputStream类介绍
数据追加续写 每次程序运行,创建输出流对象,都会清空目标文件中的数据.如何保目标文件中的数据,还能继续添加新数据呢? public FileOutputStream(File file,boolean ...