函数声明

C++编译过的C代码为什么要用extern C

。_饼干妹妹 提交于 2020-02-25 23:35:35
首先extern关键字: extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。相反,static关键字则是只能在本模块中使用。 通常,在模块的 头文件 中对本模块 提供给其它模块引用的函数和全局变量 以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块A编译生成的目标代码中找到此函数 extern "C": extern "C"是连接申明(linkage declaration),被extern "C"修饰的变量和函数是按照C语言方式编译和连接的, extern "C"必须出现在函数的第一次声明上。 作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为: void foo( int x, int y ); 该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。_foo_int

extern “c”

天大地大妈咪最大 提交于 2020-02-25 23:33:19
extern "C"的双重含义 1.被它修饰的目标是“extern ”; 2.被它修饰的目标是“C ”。 让我们来详细解读这两重含义。 被extern "C"限定的函数或变量是extern类型的。 extern 是C/C++ 语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。记住下列语句: extern int a; 仅仅是一个变量的声明,其并不是在定义变量a ,并未为a 分配内存空间。变量a 在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。 引用一个定义在其它模块的全局变量或函数(如全局函数或变量定义在A 模块,B 欲引用)有两种方法: 1.B 模块中include 模块A 的头文件; 2.模块B 中对欲引用的模块A 的变量或函数重新声明一遍,并前加extern 关键字。 通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern 声明。例如,如果模块B 欲引用该模块A 中定义的全局变量和函数时只需包含模块A 的头文件即可。这样,模块B 中调用模块A 中的函数时,在编译阶段,模块B 虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块A 编译生成的目标代码中找到此函数。 与extern 对应的关键字是static ,被它修饰的全局变量和函数只能在本模块中使用。因此

Swift简单入门教程

こ雲淡風輕ζ 提交于 2020-02-25 13:00:42
编程语言教程中的第一个程序应该在屏幕上打印“Hello, world”。在 Swift 中,可以用一行代码实现:   println("hello, world") 如果你写过 C 或者 Objective-C 代码,那你应该很熟悉这种形式——在 Swift 中,这行代码就是一个完整的程序。你不需要为了输入输出或者字符串处理导入一个单独的库。全局作用域中的代码会被自动当做程序的入口点,所以你也不需要main函数。你同样不需要在每个语句结尾写上分号。 注意:为了获得最好的体验,在 Xcode 当中使用代码预览功能。代码预览功能可以让你编辑代码并实时看到运行结果。 简单值 使用let来声明常量,使用var来声明变量。一个常量的值在编译时并不需要获取,但是你只能为它赋值一次。也就是说你可以用常量来表示这样一个值:你只需要决定一次,但是需要使用很多次。 var myVariable = 42 myVariable = 50 let myConstant = 42 常量或者变量的类型必须和你赋给它们的值一样。然而,声明时类型是可选的,声明的同时赋值的话,编译器会自动推断类型。在上面的例子中,编译器推断出myVariable是一个整数(integer)因为它的初始值是整数。 如果初始值没有提供足够的信息(或者没有初始值),那你需要在变量后面声明类型,用冒号分割。 let

Standard C Episode 4

放肆的年华 提交于 2020-02-25 10:21:41
稍微简单的复杂数据类型:数组 计算机程序处理的对象是数据信息(计算机中的信息包括数据信息和控制信息),计算机内存可以存储大量信息,姑且可以认为只有存储在内存中的数据信息才是可 以使用的。内存由操作系统管理,程序要使用内存存储空间需要向操作系统申请并被成功分配后才可以使用,C语言提供的变量声明(定义)语句可以实现向操作系 统申请存储空间。 C语言提供的变量声明(定义)语句实现向操作系统申请存储区(存储空间),变量名有"两个代表",一是代表所申请到的存储区,一是代表存储区里面存放的数 据信息。数组声明(定义)语句可以实现一次性向操作系统申请成倍的存储空间,数组名有"两个代表",一是代表所申请到的(整个)存储区,二是代表着获得的 成倍存储空间的首存储单元首地址。要注意的是:数组名根本不能代表所申请的全部存储区里面存放的数据信息。数组的"数组名"和函数的"函数名"非常类似, 数组名代表数组首元素的首地址,函数名代表函数中首条代码的地址(我们知道,程序语句可以分组,顶级分组就是函数)。 附: /* * 函数指针:指向函数的指针 * * 函数名称代表函数本身整个存储区,函数名称还代表着函数中的第一条语句的地址。函数名取址是函数地址,是整个函数的地址。这和数组名称一样,数组名称代表数组本身的整个存储区,数组名称还代表数组第一个元素的地址。数组名取址是整个数组的地址。 * * 函数地址。

ES6躬行记(14)——函数

梦想的初衷 提交于 2020-02-25 07:46:01
  在前面的章节中,已陆陆续续介绍了ES6为改良函数而引入的几个新特性,本章将会继续讲解ES6对函数的其余改进,包括默认参数、元属性、块级函数和箭头函数等。 一、默认参数   在ES5时代,只能在函数体中定义参数的默认值,而自从ES6引入了默认参数(Default Parameter)后,就能让参数在声明时带上它的默认值,如下代码所示,func2()函数中的参数默认值在可读性和简洁性方面更为优秀。 function func1(name) { name = name || "strick"; //ES5的参数默认值 } function func2(name = "strick") { //ES6的参数默认值 } 1)undefined   只有当不给参数传值或传入undefined时,才会使用它的默认值。即使传入和undefined一样的假值(例如false、null等),也得不到它的默认值,如下所示。 function func(name = "strick") { return name; } func(undefined); //"strick" func(false); //false func(null); //null 2)位置   默认参数既可以位于普通参数之前,也可以位于其之后。例如下面的两个函数,都包含两个参数,其中一个带有默认值,依次执行,都能得到预期的结果。

转载 js函数声明和函数表达式

南楼画角 提交于 2020-02-24 07:21:30
在js中函数有两种表达方式。1 函数声明 2 函数表达式 函数声明 function sayname(){ alert("li lei"); } 函数表达式 var sayname=function(){ alert("lilei"); } 函数声明会进行函数提升,但是函数表达式不能。 函数提升比变量提升优先级要高。 这是一篇比较好的文章 --------------------- 作者:qq_30022055 来源:CSDN 原文:https://blog.csdn.net/qq_30022055/article/details/79733973 版权声明:本文为博主原创文章,转载请附上博文链接! 来源: https://www.cnblogs.com/Jeely/p/10714918.html

ES6语法

六眼飞鱼酱① 提交于 2020-02-23 17:37:05
ES6语法 let 和 const 关键字 我们以前都是使用 var 关键字来声明变量的 在 ES6 的时候,多了两个关键字 let 和 const ,也是用来声明变量的 只不过和 var 有一些区别 1. let 和 const 不允许重复声明变量 // 使用 var 的时候重复声明变量是没问题的,只不过就是后的会把前面覆盖掉 var num = 100 var num = 200 2、let和const声明的变量不会进行声明提升。(通过let声明变量,之前的区域,叫做暂时性死区) 3、let和const声明的变量会被所有的代码块限制作用域(作用域更小),只要遇到大括号就形成作用域。 let num; alert(num); //undefined const num2 = 20; alert(num2); // 使用const 重复声明变量的时候就会报错 const num = 100 const num = 200 // 这里就会报错了 ii. let 和 const 声明的变量不会在预解析的时候解析(也就是没有变量提 升) alert(num); const num = 10; alert(num);` iii. let 和 const 声明的变量会被所有代码块限制作用范围 // var 声明的变量只有函数能限制其作用域,其他的不能限制 if (true) { var

C++静态成员

↘锁芯ラ 提交于 2020-02-22 19:19:20
类中的静态成员真是个让人爱恨交加的特性。我决定好好总结一下静态类成员的知识点,以便自己在以后面试中,在此类问题上不在被动。 静态类成员包括静态数据成员和静态函数成员两部分。 一 静态数据成员: 类体中的数据成员的声明前加上static关键字,该数据成员就成为了该类的静态数据成员。和其他数据成员一样,静态数据成员也遵守public/protected/private访问规则。同时,静态数据成员还具有以下特点: 1.静态数据成员的定义。 静态数据成员实际上是类域中的全局变量。所以,静态数据成员的定义(初始化)不应该被放在头文件中。 其定义方式与全局变量相同。举例如下: xxx.h文件 class base{ private: static const int _i;//声明,标准c++支持有序类型在类体中初始化,但vc6不支持。 }; xxx.cpp文件 const int base::_i=10;//定义(初始化)时不受private和protected访问限制. 注:不要试图在头文件中定义(初始化)静态数据成员。在大多数的情况下,这样做会引起重复定义这样的错误。即使加上#ifndef #define #endif或者#pragma once也不行。 2.静态数据成员被 类 的所有对象所共享,包括该类派生类的对象。即派生类对象与基类对象共享基类的静态数据成员。举例如下: class

作用域 属性链接 存储类型

你离开我真会死。 提交于 2020-02-22 10:21:23
一:作用域: 4中不同类型的作用域:代码块作用域,函数作用域,文件作用域和原型作用域 1:代码块作用域: 一对花括弧的代码称作一个代码块,任何在花括弧开始声明的标识符都具有代码块作用域 形参隐藏的问题:       K&RC中,形参在函数体外的声明中开始变生效,如果在函数体内有同名的表示服,他们就会将形参隐藏。       ANSIC中避免了这种情况,他把形参的作用域定义在函数最外层的那个函数体,也就是整个函数体,这样,声明与函数最外的局部变量无法和形参同名,因为他们的作用域相同 2:文件作用域: 任何在所有代码块之外声明的表示符都具有文件作用域 3:原型作用域: 函数原型中声明的参数名 只是为了防止名字冲突,但是并不是很有必要 4:函数作用域 他只是适用于语句标签,语句标签用于goto语句 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------分割线 ------------------------------------------------------------

C++ Primer Plus第6版18个重点笔记

╄→尐↘猪︶ㄣ 提交于 2020-02-21 06:32:43
下面是我看《C++ Primer Plus》第6版这本书后所做的笔记,作为备忘录便于以后复习。 笔记部分 C++的const比C语言#define更好的原因? 首先,它能够明确指定类型,有类型检查功能。 其次,可以使用C++的作用域规则将定义限制在特定的函数或文件中。 第三,可以将const用于更复杂的类型,比如数组和结构。 C语言中也有const,其与C++中const的区别是: 一是作用域规则不同;另一个是,在C++中可以用const值来声明数组长度。 不能简单地将整数赋给指针,如下所示: int *ptr; ptr = 0xB8000000; // type mismatch 在这里,左边是指向int的指针,因此可以把它赋给地址,但右边是一个整数。您可能知道,0xB8000000是老式计算机系统中视频内存的组合段偏移地址,但这条语句并没有告诉程序,这个数字就是一个地址。在C99标准发布之前,C语言允许这样赋值。但C++在类型一致方面的要求更严格,编译器将显示一条错误消息,通告类型不匹配。要将数字值作为地址来使用,应通过强制类型转换将数字转换为适当的地址类型: int *ptr; ptr = (int *) 0xB8000000; // type now match 这样,赋值语句的两边都是整数的地址,因此这样赋值有效。 注意