理解头文件(.h)、库文件(.lib)、和动态链接库文件(.dll),Fortran中的预处理及Fortran中function的简单使用

2023-05-16

文章目录

  • 问题来源
  • 我的问题
  • 头文件、库文件和动态链接库
    • 头文件.h
    • 库文件.lib
    • 动态链接库.dll
    • 三者的关系
      • 静态链接
      • 动态链接
  • 初识 Fortran 预处理
    • 包含文件 include
  • Fortran中function简单使用
    • 声明interface调用function
    • 声明function
    • 结论
  • 附录
    • vcmul.f
    • _rms.fi

问题来源

课题需要用Ansys做拓扑优化计算,有限元计算部分可以用APDL直接进行,而优化部分需要从ANSYS提取结构刚度矩阵等数据进行计算。ANSYS给出的是数据接口是用Fortran写的,因此课题组一直都是用APDL + Fortran进行计算。
  之前用的环境是vs 2005 + ivf,有点太老了用着不太舒服所以折腾了快一个礼拜搞了vs2017 + Intel 2019全家桶和VSCode + gfortran + lapack两套开发环境。(为了方便实验室的师弟师妹,已经做了两套教程,后面陆续会补上。这不是重点
  在折腾的过程中遇到了一点关于库函数的问题问题,让我对自己已有的对程序库函数还有头文件的理解产生了怀疑,因此专门去网上查了头文件(.h)、库文件(.lib)、和动态链接库文件(.dll)的关系。

我的问题

上网翻了一些资料,发现我对对头文件、库函数和动态连接库的理解没有大问题。理清思路之后,发现困扰我的其实是下面两个问题。

  • Fortran中的对包含文件 include(头文件)的预处理
  • Fortran中自定义函数的(声明)使用方式

为了防止以后时间长了又忘记了,将查阅内容总结如下:

  1. 头文件、库文件和动态链接库
  2. 初识 Fortran 预处理
  3. Fortran中function的简单使用

头文件、库文件和动态链接库

参考了博客园和CSDN的这两篇帖子。对每种文件依次回答如下问题:这个文件

  • 是什么?
  • 有什么作用?
  • 什么时候需要?
  • 在哪里存放?

头文件.h

头文件作为一种包含功能函数、数据接口声明的载体文件,主要用于保存 函数的声明。.h头文件是 编译时必须的。C\C++标准库头文件一般都存放在 /include目录下。

库文件.lib

lib库是一种可执行代码的二进制形式,是别人已经写好、适用成熟、在遵守相关协议下可以复用被操作系统载入内存中执行的代码。 lib库文件存放 函数的定义(实现),是 链接时需要的。库文件一般存放在 /lib文件下。
  lib库文件分为静态库和动态链接库(.dll)的导入库。

动态链接库.dll

dll库文件存放的是 函数可执行代码,一般在 /bin/lib文件夹下。动态库dll是程序 运行时需要的。

三者的关系

简单来说,库文件通过头文件向外导出接口,用户通过头文件找到库文件中需要的函数实现代码进行链接至程序当中。不理解不用纠结,先往下看。

静态链接

静态链接用到的lib库文件叫做 静态链接库
  简而言之,静态连接就是头文件告诉编译器要用到的函数是什么样子,然后编译器去lib文件里将程序运行时用到的指令和数据找出来,并将它们从lib中复制出来全部打包到可执行程序exe中。
  运行程序时将它们提取出来装入内存中,使得程序可以顺利运行,因此程序运行的时候不再需要其它的库文件。这种方式虽然简单但是粗暴,不仅使得exe程序很臃肿而且极大程度的浪费内存空间。

动态链接

动态链接用到的lib库文件叫做 动态链接库导入库,dll库叫做 动态链接库
  针对静态链接的缺点,动态链接将exe运行时需要的数据和指令的具体内容存在dll中,exe本身并不储存这些数据。在运行的时候,exe再将它们从dll中提取出来,这样exe程序就不会很臃肿。
  虽然h头文件告诉了程序要用的函数是什么样子,但是程序怎么直到到底在哪个dll中找到所需的函数指令和数据呢?这就是导入库lib的作用了。
  lib将接口操作和数据(用什么方法,从哪个dll库,(库中)什么地方调用所需函数和数据)告诉编译器并将它们放在exe中。程序运行时找到对应的dll库,将所需的内容提取出来。因此IDE设置时附加依赖项的是lib不是dll,dll是动态链接程序运行时必须的。
  不同的程序可以从同一个dll中提取所需指令和数据,因此dll也叫共享库。对于大型项目,动态链接可以极大的节约空间,减小版本迭代时发布程序的体量。

初识 Fortran 预处理

这一节主要参考了这篇博客,摘录原文如下:

预处理在Fortran语法中并未规定,但绝大多数编译器做了相应扩充。本文介绍了部分编译器环境下的Fortran预处理语句,例如宏定义、包含语句、条件编译等。
  预处理,是编译器在 编译之前,对源代码进行的一些“替换”、“选择” 等操作。它对于代码的宏观控制、维护、跨平台等都有很好的作用。
> 注意,预处理只是简单的对源代码文件进行替换,与 Fortran 的语法并没有直接关系。预处理的结果,才是真正的 Fortran 源代码,并交给编译器编译成二进制的目标代码。这个过程大概如下图:
在这里插入图片描述
  然而,Fortran 语法中,并没有规定任何预处理的内容。因此,一部分编译器扩充了自己的预处理语句,也有一些编译器使用了现成的 C 语言的预处理器,于是继承了 C 语言预处理的写法。
  本文会介绍一部分的预处理语句,但并不能保证他们能在读者的编译器上使用。请读者 阅读自己使用的编译器帮助文档,以便了解该编译器支持的预处理语句和使用方法。

包含文件 include

包含文件被大量应用在 C 语言头文件中。但 Fortran 本身并不需要子程序的原型,函数也使用(interface接口)而不是原型。module 用 mod 文件实现接口。所以,Fortran 并不需要头文件。
  在较老的代码中,由于大量使用了 common 共享数据。因此,常常把 common 里的数据定义放入 include 文件。
  包含文件其实非常简单,它完全等效于打开被包含文件,全选,复制,然后粘贴在 include 语句处。它只是一个预处理的语句,并不参与语法的任何编译,也没有 module 或其他语法那样复杂的逻辑关系。
在这里插入图片描述
  被包含文件(如 inc.h)只是简单的用文件内容替换 include 语句,它可以是任何文件名和扩展名(如 .h 或 .inc 或 .par 或任何扩展名),只要它实际上是书写有 fortran 代码的文本文件。
  此外,如果包含文件(如name.f90)是自由格式,那么被包含文件(如 inc.h)也必须是自由格式。如果一个是固定格式,另一个也必须是固定格式。
  需要注意的是,由于被包含文件(如 inc.h)已经被替换到 name.F90 文件中。因此,它不能再被编译参与链接。所以,它不必,也不能出现在工程、解决方案中。这是区别于“多文件编译连接”的。

Fortran中function简单使用

Fortran中function、subroutine、 interface和module的简单使用主要参考了这篇CSDN博客。原文内容可以直接点进去看,这里只总结一下我的问题。

声明interface调用function

我在参考Intel MKL库调用的例子时,有如下的程序开头:

!    vcMul  Example Program Text
!*******************************************************
      include "_rms.fi"
      program MKL_VML_TEST
      include "mkl_vml.f90"
      ...

其中"_rms.fi"中定义了程序program MKL_VML_TEST中调用的sub函数,"mkl_vml.f90"在MKL的include文件夹下,里面定义了MKL_VML函数的使用接口。根据上一节对于Fortran对于include文件的处理,相当于在代码里定义了sub子函数和function的接口interface。这个程序例子能够正常运行,也验证了与前面的叙述正确性。

声明function

当我参考另一个MKL库的调用例子ZDOTU_MAIN时,我发现这个例子里并没有关于MKL库函数的接口声明,而是只用external ZDOTUcomplex*16 ZDOTU声明了MKL函数ZDOTU是外部函数和它的返回数据类型。

!      Z D O T U  Example Program Text
!*****************************************************
 program  ZDOTU_MAIN
*
      integer    n, incx, incy
      integer    xmax, ymax
      parameter  (xmax=20, ymax=20)
      complex*16 x(xmax), y(ymax), res
      integer    i
*       Intrinsic Functions
      intrinsic  abs
*       External Subroutines
      external   ZDOTU, PrintVectorZ
      complex*16 ZDOTU
      ...

这个例子我没有成功运行,但是我仿照它的格式写了一个测试函数program testblas:

program testblas
    implicit none
    !external sdot
    real sdot !声明BLAS库函数 实数向量内积
    real::a(2)=(/1,1/),c(2),b(2)=(/2,3/),d

    call scopy(2,a,1,c,1)  !调用BLAS库scopy函数,讲向量a复制给c
    print*,"scopy函数"
    print*,"a"
    print*,a
    print*,"c"
    print*,c

    print*,"sdot函数"
    d = sdot(2,a,1,b,1)
    print*,"d"
    print*,d
end program testblas

程序调用BLAS库的实数向量内积sdot函数和实数向量复制scopy函数进行向量运算,程序运行结果如下:
在这里插入图片描述  这说明Fortran程序调用funtion函数,可以不用声明函数原型(定义接口,说明function的参数类型及返回数据类型),只在程序开头声明函数返回类型即可。通过实验,将program testblas中前三行替换以下两种种写法也可以通过编译。

  • 写法a
	implicit none
    external,real sdot	!声明BLAS库函数 实数向量内积
  • 写法b
	!implicit none
    external sdot	 !声明BLAS库函数 实数向量内积

结论

结合在网上找的资料,最后得出结论:

1. 可以通过(1)定义interface调用function函数。
2. 也可以声明‘type functionname’的方式,即以function函数的返回数据类型 + 函数名声明自定义function函数并在程序中调用。
3. 通过‘type functionname’声明function函数时,建议使用写法a的形式。implicit none保证没有隐式类型,external说明是外部定义函数避免混淆(比如把函数当初变量)。

附录

为了方便以后验证,这里给出program MKL_VML_TEST源码。

vcmul.f

!  Content:
!    vcMul  Example Program Text
!*******************************************************************************
      include "_rms.fi"
      
      program MKL_VML_TEST
      
      include "mkl_vml.f90"
      real(kind=4) :: srelerr
      real(kind=8) :: drelerr
      real(kind=4) :: crelerr
      real(kind=8) :: zrelerr

      complex(kind=4) cA(10)
      complex(kind=4) cB(10)
      complex(kind=4) cBha0(10)
      complex(kind=4) cBha1(10)
      complex(kind=4) cBha2(10)
      complex(kind=4) cBla1(10)
      complex(kind=4) cBla2(10)
      complex(kind=4) cBep1(10)
      complex(kind=4) cBep2(10)

      real(kind=4) CurRMS,MaxRMS

      integer(kind=8) mode
      integer tmode
      integer i, vec_len

      vec_len=10
      MaxRMS=0.0

      cA( 1)=(-100.0000,100.0000)
      cA( 2)=(-77.7777,77.7777)
      cA( 3)=(-55.5555,55.5555)
      cA( 4)=(-33.3333,33.3333)
      cA( 5)=(-11.1111,11.1111)
      cA( 6)=(11.1111,-11.1111)
      cA( 7)=(33.3333,-33.3333)
      cA( 8)=(55.5555,-55.5555)
      cA( 9)=(77.7777,-77.7777)
      cA(10)=(100.0000,-100.0000)
      cB( 1)=(0.0000000000000000e+000,-2.0000000000000000e+004)
      cB( 2)=(0.0000000000000000e+000,-1.2098741959948209e+004)
      cB( 3)=(0.0000000000000000e+000,-6.1728271672816772e+003)
      cB( 4)=(0.0000000000000000e+000,-2.2222179836717260e+003)
      cB( 5)=(0.0000000000000000e+000,-2.4691309516836372e+002)
      cB( 6)=(0.0000000000000000e+000,-2.4691309516836372e+002)
      cB( 7)=(0.0000000000000000e+000,-2.2222179836717260e+003)
      cB( 8)=(0.0000000000000000e+000,-6.1728271672816772e+003)
      cB( 9)=(0.0000000000000000e+000,-1.2098741959948209e+004)
      cB(10)=(0.0000000000000000e+000,-2.0000000000000000e+004)

      call VCMUL(vec_len,cA,cA,cBha0)

      mode=VML_EP
      call VMCMUL(vec_len,cA,cA,cBep1,mode)

      tmode=VML_EP
      tmode=VMLSETMODE(tmode)
      call VCMUL(vec_len,cA,cA,cBep2)

      mode=VML_LA
      call VMCMUL(vec_len,cA,cA,cBla1,mode)

      tmode=VML_LA
      tmode=VMLSETMODE(tmode)
      call VCMUL(vec_len,cA,cA,cBla2)

      mode=VML_HA
      call VMCMUL(vec_len,cA,cA,cBha1,mode)

      tmode=VML_HA
      tmode=VMLSETMODE(tmode)
      call VCMUL(vec_len,cA,cA,cBha2)

      do i=1,10
          if(cBha0(i) .ne. cBha1(i)) then
              print *,"Error! Difference between VCMUL and"
              print *," VMCMUL in VML_HA mode detected"
              stop 1
          endif
          if(cBha1(i) .ne. cBha2(i)) then
              print *,"Error! Difference between VCMUL and"
              print *," VMCMUL in VML_HA mode detected"
              stop 1
          endif
          if(cBla1(i) .ne. cBla2(i)) then
              print *,"Error! Difference between VCMUL and"
              print *," VMCMUL in VML_LA mode detected"
              stop 1
          endif
          if(cBep1(i) .ne. cBep2(i)) then
              print *,"Error! Difference between VCMUL and"
              print *," VMCMUL in VML_EP mode detected"
              stop 1
          endif
      end do

      print *,"vcMul test/example program"
      print *,""
      print *,"                    Arguments                         ", &
     &        "      vcMul"
      print *,"======================================================", &
     &        "========================"
      do i=1,vec_len
            print 10,cA(i),cA(i),"    ",cBha0(i)
            CurRMS=crelerr(cB(i),cBha0(i))
            if(CurRMS>MaxRMS) MaxRMS=CurRMS
      end do

      print *,""
      if(MaxRMS>=1e-5) then
            print 11,"Error! Relative accuracy is ",MaxRMS
            stop 1
      else
            print 11,"Relative accuracy is ",MaxRMS
      endif

10    format(E12.3,E12.3,E12.3,E12.3,A5,E12.3,E12.3)
11    format(A,F25.16)

      end

_rms.fi

!  Content:
!    routines for relative error calculation
!*******************************************************************************

      real(kind=4) function sfabs(a)

      real(kind=4) :: a

      if(a>=0.0) then
        sfabs=a
      else
        sfabs=-1.0*a
      endif

      end function


      real(kind=8) function dfabs(a)

      real(kind=8) :: a

      if(a>=0.0) then
        dfabs=a
      else
        dfabs=-1.0d+000*a
      endif

      if(dfabs<1e-15) then
        dfabs=1e-15
      endif

      end function


      real(kind=4) function srelerr(a,b)

      real(kind=4) :: a
      real(kind=4) :: b
      real(kind=4) :: sfabs

      srelerr=sfabs((a-b)/a)

      end function


      real(kind=8) function drelerr(a,b)

      real(kind=8) :: a
      real(kind=8) :: b
      real(kind=8) :: dfabs

      drelerr=dfabs((a-b)/a)

      end function


      real(kind=4) function crelerr(a,b)

      complex(kind=4) :: a
      complex(kind=4) :: b
      real(kind=4) :: sfabs

      real(kind=4) re
      real(kind=4) im

      re=sfabs((REAL(a)-REAL(b))/REAL(a))
      im=sfabs((AIMAG(a)-AIMAG(b))/AIMAG(a))

      if(re>=im) then
        crelerr=re
      else
        crelerr=im
      endif

      end function


      real(kind=8) function zrelerr(a,b)

      complex(kind=8) :: a
      complex(kind=8) :: b
      real(kind=8) :: dfabs

      real(kind=8) re
      real(kind=8) im

      re=dfabs((REAL(a)-REAL(b))/REAL(a))
      im=dfabs((AIMAG(a)-AIMAG(b))/AIMAG(a))

      if(re>=im) then
        zrelerr=re
      else
        zrelerr=im
      endif

      end function

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

理解头文件(.h)、库文件(.lib)、和动态链接库文件(.dll),Fortran中的预处理及Fortran中function的简单使用 的相关文章

  • extern “C”的用法和作用

    extern 34 C 34 的主要作用就是为了能够正确实现C 43 43 代码调用其他C语言代码 xff0c 实现C 43 43 与C及其它语言的混合编程 加上extern 34 C 34 后 xff0c 会指示编译器这部分代码按C语言的
  • Qt中常用的控件详细介绍

    这里写目录标题 1 容器的布局系统提供的布局控件利用 widget 做布局 2 QListWidget xff08 列表控件 xff09 3 QTreeWidget xff08 树控件 xff09 4 QTableWidget xff08
  • Qt中三种定时器的触发方式

    定时器QTimer控件 定时器触发方式3种所需api资料 1 定时器事件 触发案例1 xff1a 定时器事件案例2 xff1a 同时启动多个定时器 2 定时器对象 触发案例3 xff1a 通过定时器对象 定时 3 静态成员函数 触发案例4
  • shell脚本语言(超全超详细)

    shell脚本语言 1 shell的概述2 脚本的调用形式打开终端时系统自动调用 xff1a etc profile 或 bashrc 3 shell语法初识3 1 定义以开头 xff1a bin bash3 2 单个 34 34 号代表注
  • post请求百度网址内容和访问本地springmvc工程controller

    1 xff0c 访问百度 import java io BufferedReader import java io InputStreamReader import java io PrintWriter import java net U
  • 音乐播放器mplayer的简单使用

    mplayer 1 mplayer的安装2 mplayer的键盘模式基本控制键 xff1a 3 Slave模式 xff1a 启动方法一 xff1a 在终端下敲命令来启动mplayerMplayer 在slave模式下常用的命令 xff1a
  • AJAX和CGI 技术的应用

    AJAX xff0c CGI 一 AJAX1 AJAX的概述AJAX局部更新网页流程图 xff1a 异步流程 xff1a 2 AJAX的通信过程2 1 创建xmlHttpRequest对象2 2 设置服务器响应的回调函数标准的XMLHttp
  • W25QXX使用教程

    W25QXX是华邦公司生产的一块FLASH储存芯片 那W25Q256为例 xff1a 驱动方式 xff1a 单路双路四路SPI QSPI xff1b 擦写周期 xff1a 10W次 支持电压 xff1a 2 7 3 6V 频率 xff1a
  • QT串口通信

    QT串口的使用 1 添加头文件2 串口通信的7个步骤3 发送接收数据 1 添加头文件 span class token macro property span class token directive keyword include sp
  • Qt存储图片到数据库&&从数据库读取图片

    使用Qt将图片存储到sqlite my sql span class token double colon punctuation span span class token function my sql span span class
  • SQL常用语句大全

    创建表and插入数据 课程表 span class token keyword create span span class token keyword database span stuinfo span class token comm
  • 2020-08-21 多路复用TCP双向通信

    多路复用TCP双向通信 首先说一下多路复用 多路的作用 xff1a 监测文件描述符的状态变化 监测文件描述符是否有数据可读写 状态变化 xff1a 有数据可读 xff0c 有数据可写 xff0c 异常 有可能需要监测多个文件描述符 多个文件
  • ros中gmapping建图

    准备 1之前在github上下载的双轮差速小车中有该小车的gmapping和键盘控制的文件可以直接用 2如果之前安装的不是ros的full版本还需要下载gmapping功能包 sudo apt get install ros indigo
  • ros导航仿真——定位与路径规划

    准备 之前在github上下载的差速双轮小车不仅有其对应的gmapping还有amcl和move base xff0c 其中amcl用于定位 xff0c move base 用于路径规划 首先启动小车 roslaunch diff whee
  • arm底层通讯接口之uart

    1 目的 写这篇博文的主要目的就是让其他初学者能够更快的理解 掌握uart串口通讯 xff0c 在学习底层接口通讯的时候 xff0c 我们要带着这么几个问题 xff1a 1 xff09 什么是uart 2 xff09 uart有什么用 3
  • ros中Odom话题与odom坐标系的理解

    odom话题发表的是odom坐标系到base link之间的转换关系 xff0c 以及机器人的速度 其中base like是机器人本体坐标系 xff0c 与机器人中心重合 xff0c 所以odom坐标系到base link之间的转换关系也就
  • 多机器人导航与编队(一)

    多个机器人中让领导者导航 xff0c 相比于单个机器人导航需要修改的参数如下 主要是多机器人中的领导者与单个机器人发布的话题名称不一样 小车启动文件设置与简化 1设置 在小车的xacro文件的diff插件中添加 span class tok
  • 多机器人导航与编队(二)

    小车导航文件设置 导航分为两部分 xff1a 定位amcl和规划move base xff08 我自己的项目 导航对应ares1 maze2 amcl launch里面包含ares1 amcl launch xml 对应定位amcl xff
  • 多个小车相同功能的节点编写以及launch文件相关设置

    对于n个小车的相同功能 xff0c 写cpp 1写n个cpp 2写1个cpp xff0c 将n个小车的内容集中到一起 3写1个cpp xff0c 长度与单个相同 在launch文件中启动n个这样相同的节点 传入n个不同的参数 关于launc
  • ROS 多机器人导航salm中的问题

    ros中slam理解 在ROS中 xff0c 进行导航需要使用到的三个包是 xff1a xff08 1 xff09 move base xff1a 根据参照的消息进行路径规划 xff0c 使移动机器人到达指定的位置 这个路径规划包括全局路径

随机推荐

  • 一文读懂串口(波形分析、起始位、数据位、停止位、空闲位)

    串口 一 串口 xff08 串行接口 xff09 二 异步串口 xff08 以下统称串口 xff09 三 重要参数1 波特率2 报文格式2 1 起始位2 2 数据位2 3 奇偶校验位2 4 停止位2 5 空闲位 四 波形1 具体连接2 波形
  • #学习笔记 keil环境下单片机模块化编程的方法

    1 选择 add new item to group 建立一个 c文件 xff0c 一个 h文件 xff0c 并且名字一致 2 h文件的写法 xff08 1 xff09 h文件中要有首位两段语言 例如 ifndef HEARTRATE H
  • 【Drone】航模遥控系统各协议简介

    最近学习了无人机的一些知识 xff0c 在关于遥控系统这部分的各种协议看的有些头大 xff0c 人都晕了 看了一些资料后终于大概理解了这套系统中那些一团乱麻般的各协议的意义 xff0c 大致总结一下 图一 遥控系统组成 这里参考FPV帮装机
  • C语言获取当前的工作路径

    在C语言中获取当前的工作路径的方法一般是用内置函数为 xff1a DWORD GetModuleFileName HMODULE hModule LPTSTR lpFilename DWORD nSize 函数的参数说明 xff1a hMo
  • C/C++的指针传递和引用传递

    相信你遇到过指针传参 值传参 引用传参 xff0c 这三个关系足够让你头脑爆炸 xff0c 搞不清楚三者的区别 但是恭喜你 xff0c 你看到了这篇文章 xff0c 小编保证你看后茅塞顿开 xff0c 一下子就顺畅了 首先 xff0c 我们
  • #define、typedef 和 using之间的联系和区别

    目录 一 define 1 含义 2 用处 1 条件编译 2 解宏 3 文件包含 二 typedef 1 含义 2 用处 1 数据类型别名 2 指针别名 3 结构体别名 4 与平台无关的数据类型 三 using 1 含义 2 用处 1 权限
  • C++四种cast的详细介绍

    目录 一 static cast 1 基本数据类型转换 2 指针和void指针的转换 3 父类和子类之间的转换 二 dynamic cast 三 const cast 1 加上const 2 去掉const xff08 1 xff09 co
  • C++内存模型简述

    目录 一 什么是内存模型 二 内存的分类 三 各分区例程 1 全局 静态存储区 2 常量区 3 栈 xff08 Stack xff09 区域 4 堆 xff08 Heap xff09 区域 四 堆和栈的区别 五 堆和自由存储区的区别 1 m
  • Eclipse的介绍和插件使用

    目录 一 Eclipse的介绍 二 快捷方式 三 常用快捷键 四 插件开发 五 插件安装 第一种 xff1a 直接复制法 第二种 xff1a 使用link文件法 第三种 xff1a 使用eclipse自带图形界面安装 第四种 xff1a 使
  • 动态时间规整算法——DTW

    没有做过机器学习的小伙伴们对这个算法应该不是特别的了解 xff0c 因为机器学习经常会用到这个算法 再将这个算法之前 xff0c 我们先看一下初中的知识点 欧几里得距离 在讲解动态时间规整算法 xff08 Dynamic Time Warp
  • C++ 中的基本输入/输出

    C 43 43 附带的库为我们提供了许多执行输入和输出的方法 在 C 43 43 中 xff0c 输入和输出以字节序列或更通常称为流的形式执行 输入流 xff1a 如果字节流的方向是从设备 xff08 例如 xff0c 键盘 xff09 到
  • 单例设计模式

    单例设计模式是一种经典的面向对象设计模式 xff0c 它允许在一个应用程序中只创建一个实例对象 xff0c 以便在整个应用程序中共享该对象的状态和行为 单例模式通常用于管理应用程序级别的资源 xff0c 例如数据库连接 线程池 配置对象等
  • 代理设计模式

    一 概述 代理设计模式是一种结构型设计模式 xff0c 它允许在一个对象和其它对象之间添加一个代理对象 xff0c 以控制对原始对象的访问 代理对象通常在访问原始对象之前或之后执行一些额外的操作 xff0c 例如记录日志 控制访问权限 缓存
  • C++线程入门:轻松并发编程

    在现代计算机应用程序中 xff0c 我们经常需要处理并发任务 xff0c 这就需要使用多线程来实现 C 43 43 是一种功能强大的编程语言 xff0c 提供了丰富的线程支持 xff0c 使得并发编程变得相对容易 C 43 43 线程是一种
  • 中断与DMA

    中断 Cortex M3256 个优先级和 128 个抢占级悬起pending 中断中断的类型中断结构 DMA通道映射源传输和目标传输寄存器中断状态寄存器和中断标志清除寄存器通道x配置DMA stream x configuration r
  • keil编译时候出现function “ ” declared implicitly的解决方法

    在警告信息function declared implicitly双引号中的 表示的是所调用函数 xff0c 在调用该函数的前加 extern 声明即可
  • 2022年高教社杯全国大学生数学建模国赛B题思路详解

    1 比赛报名与思路解析 xff08 持续更新750967193 xff09 2 比赛时间 xff1a 2022年9月15日18点到2022年9月18日20点 如下为B题思路 xff1a 先贴题目 xff1a 如下是初步分析 xff1a 无人
  • 旋转矩阵、欧拉角之间转换

    学习过程中涉及欧拉角和旋转矩阵的转换 xff0c 索性整理学习一下欧拉角四元数和旋转矩阵的概念以及matlab中的互相转换 本文摘自各大课本 xff0c 博客 xff0c 自己学习整理使用 xff0c 侵删 MATLAB矩阵乘法从左到右依次
  • ROS中C++ boost编程,类内回调函数

    首先熟悉boost bind 定义如下函数 xff1a span class token keyword int span span class token function f span span class token punctuat
  • 理解头文件(.h)、库文件(.lib)、和动态链接库文件(.dll),Fortran中的预处理及Fortran中function的简单使用

    文章目录 问题来源我的问题头文件 库文件和动态链接库头文件 h库文件 lib动态链接库 dll三者的关系静态链接动态链接 初识 Fortran 预处理包含文件 include Fortran中function简单使用声明interface调