C++编译链接的理解与static修饰全局函数

C++ static与const用法详解 目录 static的作用: 对普通变量: 1.局部变量: 2.全局变量 对类中变量: 1.成员变量 2.成员函数 const的作用: static的作用: 对普通变量: 1.局部变量: 在局部变量之前加上关键字static,局部变量就被定义成为一个局部静态变量。 1)内存中的位置:静态存储区 2)初始化:未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化) 3)作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用... 阅读详情

 

1、C++编译链接的理解

首先,C++链接的逻辑是:对构建目标target,其int main()入口函数所在的文件通过#include "myfunc_class.h"包含函数或类的声明,这些头文件内也可以写有实现从而都不需要.cpp文件,但这样做就违背了“在头文件中只包含声明使头文件内容紧凑清晰”的初衷,所以一般会在对应的"myfunc_class.cpp"文件中写有实现。然后这些“依赖文件”又可以有其他依赖文件,从而形成如下的拓扑依赖关系:

main.cpp<——myfunc_class.h(myfunc_class.cpp)<——myfunc_class3.h(myfunc_class3.cpp)

/\

|

myfunc_class2.h,myfunc_class2.cpp<——myfunc_class4.h(myfunc_class4.cpp)

g++编译器首先将#include "myfunc_class.h"包含的头文件内联地插入到包含处,但#include "myfunc_class.h"还有另一层意思是当前main.cpp可能需要"myfunc_class.cpp"文件中的声明(如果有myfunc_class.cpp的话)。最终每个.cpp文件都分别编译成.o中间文件,此时的拓扑依赖关系:

main.o<——myfunc_class.o<——myfunc_class3.o

/\

|

myfunc_class2.o<——mfunc_class4.o

接下来就是链接了,拓扑关系是明确了,但编译时还是需要自己编写CMakeLists.txt的

add_executable(mybin main.cpp myfunc_class.cpp myfunc_class2.cpp myfunc_class3.cpp myfunc_class4.cpp)

明确参与链接的.cpp文件(书写顺序无先后)。此时如果main.cpp或某中间myfunc_class.cpp虽然#include "myfunc_class3.h"但并没有使用"myfunc_class3.cpp"中实现的任何函数或类方法,那add_executable()中可以不用写入myfunc_class3.cpp,写了也没关系。

如果在add_executable()中缺少了某个在调用链中使用了其函数|类方法定义的myfunc_class4.cpp,那cmake --build .编译时会链接报错未定义的符号:

HaypinsMBP:build haypin$ cmake --build .
Scanning dependencies of target MathFunctions
[ 25%] Building CXX object MathFunctions/CMakeFiles/MathFunctions.dir/mysqrt.cxx.o
[ 50%] Linking CXX static library libMathFunctions.a
[ 50%] Built target MathFunctions
Scanning dependencies of target Tutorial
[ 75%] Building CXX object CMakeFiles/Tutorial.dir/tutorial.cxx.o
[100%] Linking CXX executable Tutorial
Undefined symbols for architecture x86_64:
  "OtherFunc()", referenced from:
      _main in tutorial.cxx.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [Tutorial] Error 1
make[1]: *** [CMakeFiles/Tutorial.dir/all] Error 2
make: *** [all] Error 2
HaypinsMBP:build haypin$

2、static修饰全局函数

static修饰全局函数:https://blog.youkuaiyun.com/yesyes120/article/details/79519753

上栗子:

otherFunc.h:

static void OtherFunc();

otherFunc.cpp:

#include<iostream>
#include "otherFunc.h"
// static void OtherFunc(){
void OtherFunc(){
    std::cout<<"calling OtherFunc() in otherFunc.cpp"<<std::endl;
}

tutorial.cxx:

#include "otherFunc.h"
int main(int argc, char* argv[]){
    OtherFunc();
    return 0;
}

CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)

# set the project name and version
project(Tutorial VERSION 1.0)

add_executable(Tutorial  otherFunc.cpp tutorial.cxx) 

此时编译会先警告:

/Users/haypin/cmake_tutorial/Step5/otherFunc.h:1:13: warning: function 'OtherFunc' has internal linkage but is not defined
      [-Wundefined-internal]
static void OtherFunc();

然后在链接时报未定义的符号,因为tutorial.cxx有#include "otherFunc.h",并且otherFunc.h中的OtherFunc()带static修饰,编译处理文本包含后,则tutorial.cxx中链接OtherFunc()时会在tutorial.cxx文件作用域内部查找实现,从而因为找不到定义报错未定义的符号。注意此时并不会链接otherFunc.cpp中的extern版本的OtherFunc()定义,因为otherFunc.cpp与tutorial.cxx是不同的文件作用域。

[100%] Linking CXX executable Tutorial
Undefined symbols for architecture x86_64:
  "OtherFunc()", referenced from:
      _main in tutorial.cxx.o
ld: symbol(s) not found for architecture x86_64

将otherFunc.h中OtherFunc()去掉static后可以成功编译链接,此时otherFunc.cpp中的OtherFunc()默认是extern的,可以被tutorial.xcc链接到。

2、static限定文件作用域的实现犯法

如果:

otherFunc.h:

 void OtherFunc();

otherFunc.cpp:

#include<iostream>
#include "otherFunc.h"
static void OtherFunc(){
// extern void OtherFunc(){
    std::cout<<"calling OtherFunc() in otherFunc.cpp"<<std::endl;
}

则报编译错:

[ 60%] Building CXX object CMakeFiles/Tutorial.dir/otherFunc.cpp.o
/Users/haypin/cmake_tutorial/Step5/otherFunc.cpp:3:13: error: static declaration of 'OtherFunc' follows non-static declaration
static void OtherFunc(){
            ^
/Users/haypin/cmake_tutorial/Step5/otherFunc.h:1:7: note: previous declaration is here
 void OtherFunc();
      ^
1 error generated.

也就是不允许在extern(non-static)的默认声明后再实现static的同名函数,编译不允许。由此杜绝了tutorial.cxx在#include "otherFunc.h"后链接otherFunc.cpp中定义的static函数,static限定文件作用域在是在编译时禁止"static declaration of 'OtherFunc' follows non-static declaration"实现的。

 

所以,static声明函数或类方法的所谓“限定文件作用域”本质上就是使被编译到otherFunc.o中间文件中的被修饰函数或方法不能被其他main.o中间文件链接到,此时,#include了被修饰函数或方法所在otherFunc.h头文件的那些.cpp会在编译链接otherFunc()函数时报错未定义的函数,因为链接不到其定义。

 

Google 人机验证(reCaptcha)无法显示解决方案 Google 人机验证无法显示解决方案第一步 安装插件Chrome/Edge 电脑版Firefox 电脑版第二步 配置插件原理参考文章 前言:为了防止机器人攻击,国外很多网站都使用了 Google reCaptcha 验证码。reCaptcha 对于国外用户非常的友好,但是… 对于国内用户就不怎么友好了。究其原因,则是国内网络全线屏蔽 Google 服务,导致 reCaptcha 完全加载不出来。这样,国内玩家就无法在对应的网站进行下一步操作了。本方案可以解决 reCaptcha 无法加载的问题。 适用 阅读详情

相关推荐

视频动作识别、行为识别、时空动作检测数据集整理(持续更新)

动作、行为、事件 在计算机视觉的相关研究中,人体的动作、行为识别是一个基础研究问题。但目前识别、检测人类的动作/行为仍然是一个巨大的挑战。这里整理下当前相关的细分任务、数据集和开源代码(持续更新中)。

人工智能算法与工程实践 3万+

源码编译安装Mysql的时候出现的错:Linking CXX static library libmysys_ssl.a

出现这个错是因为我在之前执行了这个命令报错了(缺少包),然后去安装包了,就不记得之前报错了。 cmake . \ -DCMAKE_INSTALL_PREFIX=/apps/mysql \ -DMYSQL_DATADIR=/data/mysql/ \ -DSYSCONFDIR=/etc/ \ -DMYSQL_USER=mysql \ -DWITH_INNOBASE_STORAGE_ENGINE=1 \ -DWITH_ARCHIVE_STORAGE_ENGINE=1 \ -DWITH_BLACKHOLE_STO

大数据 3852

高能物理相关软件

国内高能物理实验背景     研究物质最深层次结构及相互作用的前沿基础科学。 现代高能物理实验的要素    实例源 、 探测器、   电子学、  触发 DAQ、  原始数据、 刻度、重建 、物理分析、  成果  。 离线软件的地位和作用。    是硬件设备和物理学家的桥梁,是从数据到物理成果转化中的关键和重要的环节。 高能物理实验及其特点 独一无二性,实验规模越来越大,努力省钱(使用

Alan Zhuang的博客 3298

CMake基础(3)静态库

在 CMake 中,静态库是一种特殊的目标文件,它与共享库和可执行文件不同,在链接时需要手动添加。静态库通常以 .a 或 .lib 结尾,可以通过 CMake 的 add_library() 命令添加。0x01以下内容为补充知识点 , 学习静态库只看0x02示例就行。

我其实什么都不会 9375

STM32F4串口接收ATGM336H GPS数据,手把手教你解析NMEA协议并转换经纬度格式

本文详细介绍了如何使用STM32F4开发板通过串口接收ATGM336H GPS模块的NMEA协议数据,并解析GNRMC语句获取经纬度信息。内容涵盖硬件连接、NMEA协议深度解析、数据校验实现以及经纬度格式转换的数学原理与代码实现,为嵌入式开发者提供完整的GPS数据处理解决方案。

weixin_42522575的博客 497

Cortex-M内核DWT周期计数器:从原理到STM32实战时间测量与性能分析

在嵌入式开发中,代码执行耗时测量是性能优化的基础。除了依赖外设定时器或SysTick,ARM Cortex-M3/M4/M7内核自带的DWT(Data Watchpoint and Tracker)调试组件提供了一种极低侵入性的硬件计时方案。其内部的32位周期计数器CYCCNT跟随内核时钟递增,无需占用额外引脚或定时器资源,即可实现纳秒级分辨率的函数耗时测量、中断响应分析及延时实现。从DWT寄存器配置、周期差值计算到基于SystemCoreClock的微秒换算,开发者可以快速搭建一套轻量级性能分析工具。本文

weixin_34216614的博客 183

【Make编译控制 08】CMake动静态库

CMake编译链接动静态库

phoenixFlyzzz的博客 2246

【论文笔记】LIME: low-light image enhancement via illumination map estimation

【论文笔记】LIME: low-light image enhancement via illumination map estimation 一篇低光图像增强,引用超1000次的经典论文

weixin_45565519的博客 1793

ColMap环境配置

在ubuntu16.04上安装colmap,在make到最后时,出现link错误, 问题描述: [ 98%] Linking CXX static library libui.a [ 98%] Built target ui Scanning dependencies of target colmap [100%] Building CXX object src/exe/CMakeFiles/...

P0ny的博客 3227

HyperLynx中层叠设计实例

这两种方式有点区别,前一种方式只是增加层,需要自行修改层的类型,后一种方式可以选定为某一种类型,如果是增加信号层,软件会默认同时增加一层介质层。层叠已经有8层,按照示例的层叠有4个信号层、3个地平面层和1个电源平面层,对照进行层名称(LayerName)、介质类型(Type)及用途(Usage)设置。在这列中,有的是白色,有的是淡蓝色。白色的说明可以修改,如第一行是介质,通常在最外层的介质有两个用途,阻焊层和介质,单击该行会出现一个下拉菜单,选择SolderMask,即为阻焊层。...

小幽余生不加糖 5874

SecOC专题之新鲜值TripCnt

本系列为一步步拆解新鲜值的分发及管理而撰写文章属于原创,根据自身开发经验及理解撰写,若有错误请指出Trip Counter是新鲜值中变化最慢的一个part,并且自增到最大值时,会从头开始翻转计数。Trip Counter需要收发双方都保存,由于其变化较慢,所以不会经常进行同步该值。这就要求开发过程中保证每次对该值的读写必须要正确。

qq_22969363的博客 1154

ROS编译过程中的错误

一、catkin_make编译错误 (1)     Could not find a package configuration file provided by       "gazebo_ros_control" with any of the following names:               gazebo_ros_controlConfig.cmake         gaz...

Parker盘的博客 2万+

上海计算机学会2020年5月月赛C++乙组T2经济普查

中国正在以前所未有的力度推进脱贫攻坚,国家计划在2020年使得在现行标准下的贫困人口实现全面脱贫,为此,需要对居民的经济状况进行普查。 题目描述 给定一个正整数n,表示人口数量。一开始,每个居民拥有的财产记为a1​,a2​,⋯,an​,财产可能发生两种变化: 一种来源于个体,由某个居民的经济活动而产生。在某个时刻,某个居民的财产会直接变成某个数值,可能升高也可能降低。 一种来源于政策,在某个时刻,国家会对财产低于某个标准线全部的居民,实施政策支持,使得他们的财产全部正好到达标准线。 给定这些变

长春高老师编程 905

extern和static修饰全局变量的区别

extern static修饰全局变量的区别

hujing_Liu 9680

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

关键字static的作用

1、 关键字static的作用是什么? 正确答案: 这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用: 1). 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。 2). 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。 3). 在模块内,一个被声明为静态的函数只可被这...

zzyzgg的博客 6万+

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

C/C++中static的关键字的理解总结(对比在C和C++中的区别和相同)

前言 static关键字非常好用,特别是早期时候,对于C语言来说,就是靠static关键字完成封装性滴;常见的大型项目中,static用得非常多,并且static关键字也是面试时候的热门关键字之一。在C++中static关键字由于多了类,所以会在C语言的基础上扩展了一些关于类中成员用static关键字修饰的所以掌握非常重要。 一. C语言中的static关键字 0) static关键字的名字理解 static关键字,有人说他命名得不好?因为static翻译为中文是有安静的意思。但是,对于static关键字

呋喃吖的博客 3109

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

C++ static函数跨编译单元同名问题解析与链接原理详解

在C++编程中,编译单元与链接属性是理解代码组织与构建过程的基础概念。编译单元指经过预处理的源文件,是编译器独立处理的基本单位。链接属性决定了符号(如函数、变量)在不同编译单元间的可见性,分为外部链接、内部链接和无链接三种。static关键字在文件作用域用于控制链接性,赋予函数或变量内部链接属性,使其仅在本编译单元内可见,这是实现代码封装、避免命名冲突的重要机制。从技术价值看,合理利用内部链接能减少全局符号污染,提高模块化程度,并避免意外的符号重定义错误。在工程实践中,这一特性常用于隐藏模块内部辅助函数,或

weixin_30335353的博客 282

C/C++相关概念和易错知识点(58)(static修饰变量和函数)

在.h声明Fun()函数的地方使用static,如果有n个.c都包含了这个.h,那就告诉我们有n个完全独立的Fun()存在。在类中定义的static函数和static变量类似,它相当于类的公共区域,这个函数的特殊之处在于它的第一个参数没有this指针,这也就意味着。注意区分“包含它的文件”和“它包含的文件”,上面我举例的.h中无法调用static函数就是“它包含的文件”这种情况。我们可以在一个.c定义函数,然后在.h中声明这个函数,如果有很多.c都包含了这个.h,那就相当于告诉它们在。

SGlow0708的博客 2376

C语言知识(1) static修饰详解分享

哈喽大家好啊,今天来给大家分享c中static的使用,希望能对大家有所帮助,请大家多多点赞,收藏支持我哦~

2301_81073317的博客 1790

const和static能同时修饰成员函数吗

static的作用: 对变量: 1.局部变量: 在局部变量之前加上关键字static,局部变量就被定义成为一个局部静态变量。 1)内存中的位置:静态存储区 2)初始化:未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化) 3)作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域随之结束。 注:当static用来修饰局部变量的时...

weixin_41066529的博客 3996

static全局变量为何不能跨文件访问?深入理解编译单元与链接机制

掌握C语言static关键字全局变量用法,解析为何static全局变量无法跨文件访问。深入讲解编译单元隔离机制与链接过程,揭示作用域限制原理,适用于模块化编程场景,提升代码封装性与安全性,值得收藏。

PoliSeed的博客 807

深入理解C++ static 关键字修饰全局函数

本文摘要:C++中static修饰全局函数时,将其链接属性从外部改为内部,使函数仅在定义文件中可见。通过代码示例演示了静态全局变量/函数在不同模块中的独立性,以及普通全局函数的公共接口特性。现代C++(C++11+)推荐使用匿名命名空间替代static实现文件私有功能,因其提供更好的封装性且符合标准规范。(99字)

m0_73457176的博客 474

cpp的static的实现

前言 学习自用,有错麻烦提一下 正文 static成员变量 static修饰的值会在静态区分配空间,是在编译时期就分配了空间,(那么在没运行时就占用了可执行文件的大小吧), 可以把static与全局变量作比较,实际上的实现也是像全局变量一样额外放一个地方,全局变量放在全局区,静态变量放在静态区局区,不同之处就在于static的类成员是指定只能类来访问的,相当于static成员变量做了访问限制的全局变量 static成员函数 不同于static的成员变量,static修饰的成员函数在代码区分配内

ptgood的博客 941

C++ 重要修饰符

auto 对应自动生存周期 auto修饰符只能用在函数内的对象声明中,即仅在语句块内使用。 声明中有auto修饰符的对象具有自动生存周期。 它们仅存在于被定义的当前执行代码块中,即局部变量在进入模块时生成,在退出模块时消亡。 定义局部变量的最常见的代码块是函数。 语言中包括了关键字auto,它可用于定义局部变量。但自从所有的非全局变量的缺省值假定为auto以来,aut

Acorld 2253

ndk C++ 编译器的函数名修饰规则

前言: 最近ndk debug好痛苦,堆栈里都是C++修饰过的名字,每次转化成实际的类和方法都要脑子里转一下,虽说c++filt可以转换,但是转换后可能更蒙蔽。。。这里贴出两篇文章供参考。 c++filt -n _ZNSt6__ndk113__tree_removeIPNS_16__tree_node_baseIPvEEEEvT_S5_ void std::__ndk1::__tree_re...

along 1925

深入理解C++ static 关键字修饰全局变量

本文比较了普通全局变量和static全局变量的区别。普通全局变量可在多个文件间共享,通过extern声明即可访问;而static全局变量仅限当前文件使用,对外不可见,链接时会报错。C++推荐使用匿名命名空间替代static全局变量,既能实现相同效果(限制作用域在当前文件),又避免污染全局命名空间,是更现代安全的写法。示例代码展示了两种变量的定义与使用方式,以及匿名命名空间的实现方法。

m0_73457176的博客 529
上一篇: ERROR: Could not find a version that satisfies the requirement angles (from versions: none) ERROR: N
下一篇: cmake构建后处理事件
HayPinF
博客等级 码龄9年 175粉丝 140原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值