C和C++混合编译,extern"C"的用法

C/C++混合编程时extern "C"的使用 我们在遇到规模较大的项目时候,常常会有C\C++混用的情况,某些功能模块用C语言来实现,而另外一些则用C++。当模块之间相互提供接口供对方使用的时候,必然会看到extern "C"这个字样。那么,这篇文章就来探讨下extern "C"的作用以及使用方法。为了便于更直观的理解,全程都会使用例子的形式来描述。 1 extern "C"是啥 首先,extern "C"它是一个链接指示,一方面,在C++语... 阅读详情

第一篇:转载于C和C++混合编译

关于extern_C
通常,在C语言的头文件中经常可以看到类似下面这种形式的代码

#ifdef  __cplusplus  
extern "C" {  
#endif  


/**** some declaration or so *****/  


#ifdef  __cplusplus  
}  
#endif  /* end of __cplusplus */  

那么,这种写法什么用呢?实际上,这是为了让CPP能够与C接口而采用的一种语法形式。之所以采用这种方式,是因为两种语言之间的一些差异所导致的。由于CPP支持多态性,也就是具有相同函数名的函数可以完成不同的功能,CPP通常是通过参数区分具体调用的是哪一个函数。在编译的时候,CPP编译器会将参数类型和函数名连接在一起,于是在程序编译成为目标文件以后,CPP编译器可以直接根据目标文件中的符号名将多个目标文件连接成一个目标文件或者可执行文件。但是在C语言中,由于完全没有多态性的概念,C编译器在编译时除了会在函数名前面添加一个下划线之外,什么也不会做(至少很多编译器都是这样干的)。由于这种的原因,当采用CPP与C混合编程的时候,就可能会出问题。假设在某一个头文件中定义了这样一个函数:

int foo(int a, int b);  

而这个函数的实现位于一个.c文件中,同时,在.cpp文件中调用了这个函数。那么,当CPP编译器编译这个函数的时候,就有可能会把这个函数名改成_fooii,这里的ii表示函数的第一参数和第二参数都是整型。而C编译器却有可能将这个函数名编译成_foo。也就是说,在CPP编译器得到的目标文件中,foo()函数是由_fooii符号来引用的,而在C编译器生成的目标文件中,foo()函数是由_foo指代的。但连接器工作的时候,它可不管上层采用的是什么语言,它只认目标文件中的符号。于是,连接器将会发现在.cpp中调用了foo()函数,但是在其它的目标文件中却找不到_fooii这个符号,于是提示连接过程出错。extern “C” {}这种语法形式就是用来解决这个问题的。本文将以示例对这个问题进行说明。

首先假设有下面这样三个文件:

 /* file: test_extern_c.h */  

#ifndef __TEST_EXTERN_C_H__  

#define __TEST_EXTERN_C_H__  

#ifdef  __cplusplus  
extern "C" {  
#endif  

/*  
 * this is a test function, which calculate  
 * the multiply of a and b.  
 */  

extern int ThisIsTest(int a, int b);  

#ifdef  __cplusplus  
}  
#endif  /* end of __cplusplus */  

#endif  

在这个头文件中只定义了一个函数,ThisIsTest()。这个函数被定义为一个外部函数,可以被包括到其它程序文件中。假设ThisIsTest()函数的实现位于test_extern_c.c文件中:

/* test_extern_c.c */  

#include "test_extern_c.h"  

int ThisIsTest(int a, int b)  
{  
    return (a + b);  
}  

可以看到,ThisIsTest()函数的实现非常简单,就是将两个参数的相加结果返回而已。现在,假设要从CPP中调用ThisIsTest()函数:

/* main.cpp */  
#include "test_extern_c.h"  
#include <stdio.h>  
#include <stdlib.h>  

class FOO {  
public:  

int bar(int a, int b)  
{  
    printf("result=%i\n", ThisIsTest(a, b));  
}  
};  

int main(int argc, char **argv)  
{  
    int a = atoi(argv[1]);  
    int b = atoi(argv[2]);   

    FOO *foo = new FOO();  

    foo->bar(a, b);  

    return(0);  
}  

在这个CPP源文件中,定义了一个简单的类FOO,在其成员函数bar()中调用了ThisIsTest()函数。下面看一下如果采用gcc编译test_extern_c.c,而采用g++编译main.cpp并与test_extern_c.o连接会发生什么情况:

[cyc@cyc src]$ gcc -c test_extern_c.c  

[cyc@cyc src]$ g++ main.cpp test_extern_c.o  

[cyc@cyc src]$ ./a.out 4 5                  

result=9

可以看到,程序没有任何异常,完全按照预期的方式工作。那么,如果将test_extern_c.h中的extern “C” {}所在的那几行注释掉会怎样呢?注释后的test_extern_c.h文件内容如下:

 /* test_extern_c.h */  
#ifndef __TEST_EXTERN_C_H__  
#define __TEST_EXTERN_C_H__  

//#ifdef   __cplusplus  
//extern "C" {  
//#endif  

/*  
 * this is a test function, which calculate  
 * the multiply of a and b.  
 */  

extern int ThisIsTest(int a, int b);  


//#ifdef   __cplusplus  
//  }  
//#endif   /* end of __cplusplus */  

#endif  

除此之外,其它文件不做任何的改变,仍然采用同样的方式编译test_extern_c.c和main.cpp文件:

[cyc@cyc src]$ gcc -c test_extern_c.c  

[cyc@cyc src]$ g++ main.cpp test_extern_c.o  

/tmp/cca4EtJJ.o(.gnu.linkonce.t._ZN3FOO3barEii+0x10): In function `FOO::bar(int, int)':  

: undefined reference to `ThisIsTest(int, int)'  

collect2: ld returned 1 exit status  

在编译main.cpp的时候就会出错,连接器ld提示找不到对函数ThisIsTest()的引用。

为了更清楚地说明问题的原因,我们采用下面的方式先把目标文件编译出来,然后看目标文件中到底都有些什么符号:

[cyc@cyc src]$ gcc -c test_extern_c.c      

[cyc@cyc src]$ objdump -t test_extern_c.o  

test_extern_c.o:     file format elf32-i386  

SYMBOL TABLE:  

00000000 l    df *ABS*  00000000 test_extern_c.c  

00000000 l    d  .text  00000000  

00000000 l    d  .data  00000000  

00000000 l    d  .bss   00000000  

00000000 l    d  .comment       00000000  

00000000 g     F .text  0000000b ThisIsTest  
[cyc@cyc src]$ g++ -c main.cpp            
[cyc@cyc src]$ objdump -t main.o          
main.o:     file format elf32-i386  
SYMBOL TABLE:  

00000000 l    df *ABS*  00000000 main.cpp  

00000000 l    d  .text  00000000  

00000000 l    d  .data  00000000  

00000000 l    d  .bss   00000000  

00000000 l    d  .rodata        00000000  

00000000 l    d  .gnu.linkonce.t._ZN3FOO3barEii 00000000  

00000000 l    d  .eh_frame      00000000  

00000000 l    d  .comment       00000000  

00000000 g     F .text  00000081 main  

00000000         *UND*  00000000 atoi  

00000000         *UND*  00000000 _Znwj  

00000000         *UND*  00000000 _ZdlPv  

00000000  w    F .gnu.linkonce.t._ZN3FOO3barEii 00000027 _ZN3FOO3barEii  

00000000         *UND*  00000000 _Z10ThisIsTestii  

00000000         *UND*  00000000 printf  

00000000         *UND*  00000000 __gxx_personality_v0  

可以看到,采用gcc编译了test_extern_c.c之后,在其目标文件test_extern_c.o中的有一个ThisIsTest符号,这个符号就是源文件中定义的ThisIsTest()函数了。而在采用g++编译了main.cpp之后,在其目标文件main.o中有一个_Z10ThisIsTestii符号,这个就是经过g++编译器“粉碎”过后的函数名。其最后的两个字符i就表示第一参数和第二参数都是整型。而为什么要加一个前缀_Z10我并不清楚,但这里并不影响我们的讨论,因此不去管它。显然,这就是原因的所在,其原理在本文开头已作了说明。


[cyc@cyc src]$ gcc -c test_extern_c.c  

[cyc@cyc src]$ objdump -t test_extern_c.o  

test_extern_c.o:     file format elf32-i386  

SYMBOL TABLE:  

00000000 l    df *ABS*  00000000 test_extern_c.c  

00000000 l    d  .text  00000000  

00000000 l    d  .data  00000000  

00000000 l    d  .bss   00000000  

00000000 l    d  .comment       00000000  

00000000 g     F .text  0000000b ThisIsTest  

那么,为什么采用了extern “C” {}形式就不会有这个问题呢,我们就来看一下当test_extern_c.h采用extern “C” {}的形式时编译出来的目标文件中又有哪些符号:

[cyc@cyc src]$ g++ -c main.cpp  

[cyc@cyc src]$ objdump -t main.o  

main.o:     file format elf32-i386  

SYMBOL TABLE:  

00000000 l    df *ABS*  00000000 main.cpp  

00000000 l    d  .text  00000000  

00000000 l    d  .data  00000000  

00000000 l    d  .bss   00000000  

00000000 l    d  .rodata        00000000  

00000000 l    d  .gnu.linkonce.t._ZN3FOO3barEii 00000000  

00000000 l    d  .eh_frame      00000000  

00000000 l    d  .comment       00000000  

00000000 g     F .text  00000081 main  

00000000         *UND*  00000000 atoi  

00000000         *UND*  00000000 _Znwj  

00000000         *UND*  00000000 _ZdlPv  

00000000  w    F .gnu.linkonce.t._ZN3FOO3barEii 00000027 _ZN3FOO3barEii  

00000000         *UND*  00000000 ThisIsTest  

00000000         *UND*  00000000 printf  

00000000         *UND*  00000000 __gxx_personality_v0  

注意到这里和前面有什么不同没有,可以看到,在两个目标文件中,都有一个符号ThisIsTest,这个符号引用的就是ThisIsTest()函数了。显然,此时在两个目标文件中都存在同样的ThisIsTest符号,因此认为它们引用的实际上同一个函数,于是就将两个目标文件连接在一起,凡是出现程序代码段中有ThisIsTest符号的地方都用ThisIsTest()函数的实际地址代替。另外,还可以看到,仅仅被extern “C” {}包围起来的函数采用这样的目标符号形式,对于main.cpp中的FOO类的成员函数,在两种编译方式后的符号名都是经过“粉碎”了的。

因此,综合上面的分析,我们可以得出如下结论:采用extern “C” {} 这种形式的声明,可以使得CPP与C之间的接口具有互通性,不会由于语言内部的机制导致连接目标文件的时候出现错误。需要说明的是,上面只是根据我的试验结果而得出的结论。由于对于CPP用得不是很多,了解得也很少,因此对其内部处理机制并不是很清楚,如果需要深入了解这个问题的细节请参考相关资料。

备注:
1. 对于要在cpp中使用的在c文件中写好的函数func(),只需要在c文件的头文件中添加extern “C”声明就可以了。比如:extern “C” func() { …}

当然,可以使用

#ifdef __cplusplus

extern "C" {

#endif

和


#ifdef __cplusplus

}

#endif

将整个c文件的函数全都括起来。


第二篇:转载于extern”C” 用法解析

引言

C++保留了一部分过程式语言的特点,因而它可以定义不属于任何类的全局变量和函数。但是,C++毕竟是一种面向对象的程序设计语言,为了支持函数的重载,C++对全局函数的处理方式与C有明显的不同。
extern “C”的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern “C”后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般之包括函数名。
比如说你用C 开发了一个DLL 库,为了能够让C ++语言也能够调用你的DLL输出(Export)的函数,你需要用extern “C”来强制编译器不要修改你的函数名。

揭秘extern “C”

从标准头文件说起

#ifndef __INCvxWorksh  /*防止该头文件被重复引用*/
#define __INCvxWorksh

#ifdef __cplusplus    //__cplusplus是cpp中自定义的一个宏
extern "C" {          //告诉编译器,这部分代码按C语言的格式进行编译,而不是C++的
#endif

    /**** some declaration or so *****/  

#ifdef __cplusplus
}
#endif

#endif /* __INCvxWorksh */

extern “C”的含义

extern “C” 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;其次,被它修饰的目标是“C”的。
被extern “C”限定的函数或变量是extern类型的;
1、extern关键字
extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。
通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在链接阶段中从模块A编译生成的目标代码中找到此函数。
与extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。

2、被extern “C”修饰的变量和函数是按照C语言方式编译和链接的
首先看看C++中对类似C的函数是怎样编译的。
作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:
void foo( int x, int y );
该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。
_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。 例如,在C++中,函数void foo( int x, int y )与void foo( int x, float y )编译生成的符号是不相同的,后者为_foo_int_float。
同样地,C++中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以”.”来区分。而本质上,编译器在进行编译时,与函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。

3、举例说明
(1)未加extern “C”声明时的连接方式
假设在C++中,模块A的头文件如下:

// 模块A头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
int foo( int x, int y );
#endif
//在模块B中引用该函数:
// 模块B实现文件 moduleB.cpp
#include "moduleA.h"
foo(2,3);

实际上,在连接阶段,链接器会从模块A生成的目标文件moduleA.obj中寻找_foo_int_int这样的符号!

(2)加extern “C”声明后的编译和链接方式
加extern “C”声明后,模块A的头文件变为:


// 模块A头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
extern "C" int foo( int x, int y );
#endif

在模块B的实现文件中仍然调用foo( 2,3 ),其结果是:

<1>A编译生成foo的目标代码时,没有对其名字进行特殊处理,采用了C语言的方式;

<2>链接器在为模块B的目标代码寻找foo(2,3)调用时,寻找的是未经修改的符号名_foo。

如果在模块A中函数声明了foo为extern “C”类型,而模块B中包含的是extern int foo(int x, int y),则模块B找不到模块A中的函数;反之亦然。

extern “C”这个声明的真实目的是为了实现C++与C及其它语言的混合编程。

应用场合

C++代码调用C语言代码、在C++的头文件中使用
在C++中引用C语言中的函数和变量,在包含C语言头文件(假设为cExample.h)时,需进行下列处理:

extern "C"
{
#include "cExample.h"
}

而在C语言的头文件中,对其外部函数只能指定为extern类型,C语言中不支持extern “C”声明,在.c文件中包含了extern “C”时会出现编译语法错误。

/* c语言头文件:cExample.h */
#ifndef C_EXAMPLE_H
#define C_EXAMPLE_H
extern int add(int x,int y);     //注:写成extern "C" int add(int , int ); 也可以
#endif

/* c语言实现文件:cExample.c */
#include "cExample.h"
int add( int x, int y )
{
 return x + y;
}

// c++实现文件,调用add:cppFile.cpp
extern "C"
{
 #include "cExample.h"        //注:此处不妥,如果这样编译通不过,换成 extern "C" int add(int , int ); 可以通过
}

int main(int argc, char* argv[])
{
 add(2,3);
 return 0;
}

如果C++调用一个C语言编写的.DLL时,当包括.DLL的头文件或声明接口函数时,应加extern “C”{}。

在C中引用C++语言中的函数和变量时,C++的头文件需添加extern “C”,但是在C语言中不能直接引用声明了extern “C”的该头文件,应该仅将C文件中将C++中定义的extern “C”函数声明为extern类型


//C++头文件 cppExample.h
#ifndef CPP_EXAMPLE_H
#define CPP_EXAMPLE_H
extern "C" int add( int x, int y );
#endif

//C++实现文件 cppExample.cpp
#include "cppExample.h"
int add( int x, int y )
{
 return x + y;
}

/* C实现文件 cFile.c
/* 这样会编译出错:#include "cExample.h" */
extern int add( int x, int y );
int main( int argc, char* argv[] )
{
 add( 2, 3 );
 return 0;
}

转载于
C和C++混合编译
extern”C” 用法解析

C++和C的混合编译 简介 C++ 语言的创建初衷是 “a better C”,但是这并不意味着 C++ 中类似 C 语言的全局变量和函数所采用的编译和连接方式与 C 语言完全相同。作为一种欲与 C 兼容的语言, C++ 保留了一部分过程式语言的特点(被世人称为"不彻底地面向对象"),因而它可以定义不属于任何类的全局变量和函数。但是, C++ 毕竟是一种面向对象的程序设计语言,为了支持函数的重载, C++ 对全局函数的处理方式与 C 有明显的不同。 本文将介绍如何通过 extern “C” 关键字在 C++ 中支持 C 语言 和 阅读详情

相关推荐

C/C++ 混合编译 C++中的extern “C“

C/C++ 混合编译 C++中的extern “C” gcc编译*.c和*.cpp文件依据各自的文件类型各自编译为C型目标文件和C++类型目标文件 g++编译*.c\*.cpp文件,都是编译为C++类型的目标文件 使用g++时,不论是*.c还是*.cpp都将链接std c++库。而gcc是依据各自文件类型链接相应的std c库或者是std c++库 当一个程序有通过g++编译的C++目标模块与通过gcc编译的C目标模块时,链接会报错。案例如下: test.c int sum(int a,in

Nick_Di的博客 805

extern C的作用详解

     extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般之包括函数名。      这个功能十分有用处,因为在C++出现以前,很多代码都是C语言写的,而且很底层的库也是C语言写的,为了更好的支持原来的C代

疯狂算法~ 14万+

1.全基因组重测序数据分析介绍

二代测序原理及fastq数据解读、全基因组重测序数据分析内容

weixin_53682198的博客 1880

【C++】extern “C“详解

参考: extern “C“的作用及理解 extern C里面能有C++代码吗? 1. 概述 extern “C” 是C++特有的指令(C无法使用该指令),目的在于支持C++与C混合编程。 2. 作用 extern “C” 的作用是告诉C++编译器用C规则编译指定的代码(除函数重载外,extern “C” 不影响C++其他特性)。 3. 原因 为什么要用C规则编译C++代码呢? 因为C和C++的编译规则不一样,主要区别体现在编译期间生成函数符号的规则不一致。 C++比C出道晚,但是增加了很多优秀的功能,.

lemonxiaoxiao的博客 2139

ch32v103xx 烧写

烧写方式 串口uart, usb,swd(wch link)但不建议按此使用,参官方说明。

qq_39239990的博客 637

UUVsimulator仿真

pub -r 10 /cmd_vel geometry_msgs/Twist控制运动没有反应。通过键盘控制运动,接收不到/cmd_vel消息。

Fatal__的博客 4606

在C++程序中调用被C编译器编译后的函数,为什么要加extern “C”

C++语言是一种面向对象编程语言,支持函数重载,而C语言是面向过程的编程语言,不支持函数重载,所以函数被C++编译后在哭中的名字与C语言的不同,如果声明一个C语言函数float f(int a, char b),C++的编译器就会将这个名字变成像_f_int_char之类的东西以支持函数重载,然而C语言编译器的库一般不执行该转换,所以它的内部名为_f,这样连接器将无法解释C++对函数f()的调用。...

小肥羊快快跑 2120

SAM3模型国内快速上手:Modelscope权重下载+环境配置一条龙指南

本文详细介绍了SAM3模型在国内的快速部署方案,包括通过Modelscope平台下载权重文件、优化CUDA 11.8环境配置以及实战避坑技巧。针对国内开发者常见的网络问题和环境兼容性问题,提供了从权重下载到模型加载的全流程指南,帮助用户高效完成部署并快速上手SAM3模型。

weixin_28465009的博客 1144

编程:extern 用法 C、C++

1.引言   C++语言的创建初衷是“a better C”,但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同。作为一种欲与C兼容的语言,C++保留了一部分过程 式语言的特点(被世人称为“不彻底地面向对象”),因而它可以定义不属于任何类的全局变量和函数。但是,C++毕竟是一种面向对象的程序设计语言,为了支 持函数的重载,C++对全局函数的处理方式与C有

hzraymond的专栏 841

QGIS003:【02标注工具栏】-标注的样式、放置和属性修改

摘要:文本介绍了QGIS标注的样式、放置和属性修改

qq_31762031的博客 1917

Claude Code 完全指南:从入门到精通

《AI编程助手ClaudeCode深度指南》摘要 ClaudeCode作为新一代AI编程助手,凭借200K tokens的超长上下文窗口和深度代码理解能力,正在重塑开发工作流程。本文系统介绍了从安装配置到高级应用的完整使用指南: 核心优势包括: 项目级代码理解能力 Agent自主规划复杂任务 原生终端集成支持 多文件协同编辑功能 实战应用场景: 快速理解陌生项目架构 诊断性能瓶颈并提供优化方案 自动生成符合规范的API代码 开发可复用技术组件 高级技巧: 通过CLAUDE.md定义项目规范 合理使用/cle

分享AI、区块链技术及应用,未来已来 603

C++与C混合编译头文件陷阱全解析(资深架构师20年实战经验总结)

解决C与C++混合编译兼容难题,深入剖析混合编译的头文件常见陷阱与正确写法。涵盖extern "C"用法、头文件卫士设计、语言链接声明等关键技巧,适用于跨语言项目集成。提升代码稳定性,避免链接错误,值得收藏。

CompiTide的博客 774

001、专栏导论:为什么我们需要MLIR与算子中间表示

五年前,大家还在争论“TVM还是XLA”。现在回头看,TVM的Relay IR和XLA的HLO都是特定领域的IR,它们解决了各自的问题,但缺乏通用性。MLIR的出现,本质上是因为硬件异构化已经到了一个临界点——CPU、GPU、NPU、DSP、FPGA,每个硬件都有自己的指令集和内存层次,没有一个统一的IR能同时高效表达所有硬件的计算模式。MLIR的“方言+渐进式lowering”模式,恰好提供了这种灵活性。你可以为每个硬件定制一套方言,然后共享公共的lowering路径。

Jack010169的博客 488

C/C++混合编译中的extern “C“与#ifdef __cplusplus宏组合深度解析

在C/C++混合工程中,条件编译指令#ifdef __cplusplus与extern "C"的组合是跨语言调用和库封装的核心技术。C和C++在编译模型上存在显著差异,函数重载和命名空间等特性导致C++编译器会对符号进行名称修饰,而C语言则保持原始函数名。这一机制是许多链接错误的根源。通过extern "C"指定C链接规格,可确保C++代码正确匹配C库的符号,实现跨语言调用。实际开发中,该宏组合广泛用于头文件设计、混合编译和CMake工程中,是解决undefined reference问题的高效手段。理解其

weixin_30512965的博客 288

UFS总体介绍及FPGA开发

通过实现UFS的主控制器、设备控制器等组件,我们可以在FPGA上进行UFS开发,并实现高速数据传输和低功耗特性的存储解决方案。物理层负责传输物理信号,数据链路层提供数据包的传输和错误检测功能,传输层处理数据包的分段、重组和重传,逻辑层管理设备和主控制器之间的命令和数据传输,文件系统层负责文件管理和数据存储。在本文中,我们将介绍UFS的总体架构和特性,并探讨如何在FPGA上进行UFS开发。这些组件的实现涉及到UFS协议的具体细节和硬件平台的特性,因此需要参考UFS协议规范和FPGA开发平台的相关文档。

PodProgram的博客 2135

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

【21. extern “C“ , C和C++混合编译详解】

在实际的开发中,我们往往会遇到C和C++混合编译的场景。例如,使用C语言编写的库需要被C++程序调用,或者将C++代码与现有的C代码库集成。在这些情况下,C和C++之间的差异,尤其是函数的名称修饰(name mangling)和链接方式,会导致编译和链接错误。本文将详细介绍如何通过extern "C"解决这一问题,确保C和C++代码能够顺利互操作。C和C++语言在函数声明和链接的方式上存在差异,主要表现为C++的名称修饰机制。为了在C++中调用C语言的函数,必须使用extern "C"

涛ing的博客 1102

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

【c/c++】c和cpp混合编译

在这段代码中,#ifdef __cplusplus 和 #endif 之间的代码是为了在 C++ 中使用 C 语言的函数声明和定义时,确保编译器正确地处理 C 和 C++ 之间的语法差异。这是因为 C 和 C++ 有一些不同之处,包括函数名的重载、类型转换等。在这段代码中,extern “C” 是一个 C++ 的特性,它告诉编译器要按照 C 的方式来处理其中的函数。:这个条件编译指令检查是否正在编译 C++ 代码。__cplusplus 是一个宏,当编译器编译 C++ 代码时,它会被定义。

Accowo的博客 3844

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

ESP32的IDF实现C语言和C++语言的混合编译

ESP32C/C++混合编译

weixin_56634270的博客 2769

C++中extern关键字使用

chapter 1 . extern关键字的作用     extern是一个关键字,它告诉编译器存在着一个变量或者一个函数,如果在当前编译语句的前面中没有找到相应的变量或者函数,也会在当前文件的后面或者其它文件中定义,来看下面的例子。     // extern.cpp : Defines the entry point for the console application. // #

sruru的专栏 9万+

从C到C++ | extern关键字

摘要:extern关键字在C/C++中主要有三种用途:1. extern "C"用于解决C++和C语言之间的函数名兼容问题,通过禁止C++的名称修饰实现互调;2. extern修饰函数/变量声明,表示其定义在其他文件中,实现多文件共享;3. extern "C"修饰变量使C++变量按C规则处理,实现跨语言变量访问。其中extern "C"与函数重载冲突,使用时需注意声明与定义的区别,推荐通过条件编译编写兼容头文件。extern声明变量时需严格区分声

weixin_65043441的博客 1043

如何混合编译C语言和C++

如何混合编译C语言和C++ 实际开发过程中,C++中会调用C与语言编写的代码,我在网络上面找到一篇写得很好的文章 http://blog.youkuaiyun.com/keensword/article/details/401114 就着上面的例子,我使用C语言采用两种方法重写了一下。 方法一、全局函数和变量在devVar.c文件中实现,在extern.cpp文件中使用ex...

坚持 1989
上一篇: Linux df和du的区别
下一篇: malloc、calloc、realloc的区别
黑帽子和猫
博客等级 码龄12年 41粉丝 121原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值