jdk安装及环境变量配置、python安装及环境变量配置
假设您的计算机设置有两个/两个以上用户。当设置在用户变量中时,仅对当前用户有效,不能被其他用户使用。为了简单起见,通常将其设置在系统变量中。变量设置环境变量。输入“java -版本”。注意java后面有一个空格。输入“java”检查是否可以运行,然后输入“javac”,如图。输入“java HelloWorld”回车即可得到结果,如图。但此时如果重新编译my_handle.c,C语言编译器会报“语法错误”,因为extern "C"是C++语法,C语言编译器不识别。C++ 规范允许这种嵌套。将 #include 指令放置在 extern "C" { } 内的另一个重大风险是您可能会无意中更改函数声明的链接规范。
【需要设置两个环境变量,一个是用户变量,一个是系统变量; 用户变量仅与当前用户相关/有效,而系统变量对系统有效。 假设您的计算机设置有两个/两个以上用户。 当设置在用户变量中时,仅对当前用户有效,不能被其他用户使用。 然而,当它被设置在系统变量中时,它将对所有用户有效。 为了简单起见,通常将其设置在系统变量中。 变量设置环境变量。 】
配置环境变量,添加-->变量名:CLASSPATH
——>变量值:.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar(注意小数点)
添加:变量名称:JAVA_HOME
变量值:(你电脑上安装的jdk的位置/搜索路径)
将下图红色部分添加到Path中
检查JDK是否安装成功,在“开始”查询输入框中输入cmd,进入命令提示符窗口,如图
输入“java -版本”。 注意java后面有一个空格。 按 Enter 键后,将显示您计算机上的版本信息。 输入“java”检查是否可以运行,然后输入“javac”,如图。
使用记事本编写HelloWorld代码
在“开始”搜索窗口中输入“记事本”如图
单击“记事本”并开始编写 HelloWorld 代码。 注意在英文环境下编写代码,否则编译时会出错。 代码如下所示:
类HelloWorld{
公共静态无效主(字符串[] args){
System.out.println("helloWorld!");
保存路径:按“Ctrl+s”弹出如下窗口,将文件名改为JDK可识别的文件,后缀为“.java”,点击要保存的文件夹(我选择的文件夹名为mode文件夹),保存类型默认为文本文档,后缀为“.txt”,点击“确定”,如图。
该文件在我电脑上的位置在D盘的mode目录下,如图
首先将“.java”文件编译成“.class”文件,如下
输入“D:”并回车; 然后输入“cd模式”并回车; 然后输入“javac HelloWorld.java”并回车(如下图)。 编译完成。 在D盘下的mode目录下可以看到后缀是“.class”文件(如上图)。
或者在当前目录下输入“dir”,查看是否生成文件/查看当前目录下有哪些文件。 如图所示,后缀为“.class”和“.java”的文件位于当前D盘的mode文件夹中。 文档。
执行HelloWorld
输入“java HelloWorld”回车即可得到结果,如图。
28668787
对于我们前面的示例,如果我们将头文件 my_handle.h 的内容更改为:
然后使用C++编译器重新编译my_handle_client.cpp,生成的目标文件my_handle_client.o中的符号表变为:
由此我们可以看出,此时用extern "C"修饰的语句生成的符号与C语言编译器生成的符号是一致的。 这样,当你再次将my_handle.o和my_handle_client.o链接在一起时,就不会再出现之前的“symbol undefined”错误了。
但此时如果重新编译my_handle.c,C语言编译器会报“语法错误”,因为extern "C"是C++语法,C语言编译器不识别。 此时,您可以使用宏 __cplusplus 来识别 C 和 C++ 编译器,正如我们之前讨论的那样。 修改后的my_handle.h代码如下:
嵌入式物联网确实有很多东西需要学习。 不要学错路线和内容,导致你的薪资水涨船高!
我免费给大家分享一个数据包,差不多150G。 学习内容、面试、项目都比较新、全面! 据估计,在网上购买某种鱼至少要花费几十美元。
点此找助手0元获取:添加微信获取信息
小心门后的未知世界
了解了 extern "C" 的由来和用途后,回到我们原来的主题,为什么 #include 指令不能放在 extern "C" { ... } 内部呢?
我们先来看一个例子。 我们有ah、bh、ch和foo.cpp,其中foo.cpp包含ch,ch包含bh,bh包含ah,如下:
现在使用C++编译器的预处理选项来编译foo.cpp,得到以下结果:
正如您所看到的,当您将 #include 指令放置在 extern "C" { } 内时,它将导致 extern "C" { } 的嵌套。 C++ 规范允许这种嵌套。 当发生嵌套时,最内层的嵌套优先。 例如,在以下代码中,函数 foo 将使用 C++ 链接规范,而函数 bar 将使用 C 链接规范。
如果能够保证一个C语言头文件直接或间接依赖的所有头文件也是C语言,那么根据C++语言规范,这种嵌套应该没有问题。 但具体到某些编译器的实现,比如MSVC2005,可能会因为extern "C" { }嵌套过深而报错。 不要为此责怪微软,因为就问题而言,这种嵌套是没有意义的。 您可以通过将 #include 指令放在 extern "C" { } 之外来避免嵌套。 以前面的例子为例,如果我们将每个头文件的#include指令移到extern "C" { }之外,然后使用C++编译器的预处理选项来编译foo.cpp,我们将得到以下结果:
这样的结果绝对不会导致编译问题——即使使用MSVC。
将 #include 指令放置在 extern "C" { } 内的另一个重大风险是您可能会无意中更改函数声明的链接规范。 例如:有两个头文件ah和bh,其中bh包含ah,如下:
按照ah作者的初衷,函数foo是一个C++自由函数,它的链接规范是“C++”。 但在 bh 中,由于 #include "ah" 被放置在 extern "C" { } 内,因此函数 foo 的链接规范被错误地更改。
由于每个 #include 指令背后都隐藏着一个未知的世界,除非你刻意探索它,否则你永远不会知道当你将 #include 指令放在 extern "C" { } 中时会发生什么。 会产生什么样的结果,会带来什么样的风险。 也许你会说,“我可以检查包含的头文件,我可以确保它们不会造成麻烦。” 但何苦呢? 毕竟,我们不必为不必要的事情付出代价,对吗?
问答
问:任何 #include 指令都不能放在 extern "C" 内吗?
答:就像这个世界上的大多数规则一样,总会有特殊情况。
有时,你可能会利用头文件机制来“巧妙”地解决一些问题。 例如#pragma pack的问题。 这些头文件具有与常规头文件不同的功能。 C 函数声明或变量定义不会放置在其中,并且链接规范不会影响其内容。 在这种情况下,您不必遵守这些规则。
更一般的原则是,当你明白了所有这些原则之后,只要你明白你在做什么,那就去做吧。
Q:你只是说extern "C"不应该放进去,但是什么可以放进去呢?
答:链接规范仅用于修改函数和变量以及函数类型。 因此,严格来说,您应该只将这三种类型的对象放置在 extern "C" 内。
但是,如果将 C 语言的其他元素,例如非函数类型定义(结构体、枚举等)放在 extern "C" 内,则不会产生任何影响。 更不用说宏定义的预处理指令了。
因此,如果您重视良好的组织和管理习惯,则应该仅在必要时使用 extern "C" 语句。 即使你很懒,在大多数情况下,将标头本身的所有定义和声明放在 extern "C" 中也不会有什么大问题。
问:如果带有函数/变量声明的 C 头文件中没有 extern "C" 声明怎么办?
答:如果您知道这个头文件永远不会被 C++ 代码使用,那么就不要管它。
但现实是,在大多数情况下,你无法准确预测未来。 如果你现在加上这个extern "C",花不了多少钱,但是如果你现在不加上,以后这个头文件不小心被包含到别人的C++程序里时,别人恐怕就要付出代价了成本较高。 来定位错误并修复问题。
问:如果我的 C++ 程序想要包含一个 C 头文件啊,其内容包含 C 函数/变量声明,但它们不使用 extern "C" 链接规范,我该怎么办?
- 答:添加它啊。
有人可能会建议,如果ah没有extern "C"而b.cpp包含ah,可以添加:
这是一个邪恶的计划,原因我们之前已经解释过。 但值得探讨的是,这个解决方案背后可能有一个假设,那就是我们无法修改啊。 无法修改的原因可能来自于两个方面:
对于第一种情况,不要试图自行解决,因为这会给您带来不必要的麻烦。 正确的解决方案是将其视为错误并将缺陷报告发送给适当的团队或第三方公司。 如果您付费的是您自己公司的团队或第三方公司,他们有义务为您进行此类修改。 如果他们不明白这一点的重要性,请告诉他们。 如果这些头文件属于自由开源软件,请自行进行正确的修改,并将补丁发布给其开发团队。
第二种情况,你需要放弃这种不必要的安全意识。 因为,首先,对于大多数头文件来说,这种修改并不是复杂的、高风险的修改,一切都在可控范围之内; 其次,如果某个头文件混乱、复杂,虽然不是复杂的、高风险的修改,系统的哲学应该是:“在它引起麻烦之前不要碰它”。 但既然麻烦已经来了,与其逃避不如面对,所以最好的方针就是把它当作一个很好的机会,把它整理成干净合理的状态。
问:我们代码中extern "C"的写法如下。 它是否正确?
答:不确定。
根据C++规范,__cplusplus的值应该定义为199711L,这是一个非零值; 尽管有些编译器没有按照规范实现,但它们仍然可以保证 __cplusplus 的值不为零——至少对我来说到目前为止还没有看到任何编译器将其实现为 0。 在这种情况下,#if __cplusplus ... #endif 是完全多余的。
不过C++编译器厂家那么多,没有人能保证某个编译器,或者某个编译器的早期版本,不把__cplusplus的值定义为0。但即便如此,只要能保证宏__cplusplus只是在C++编译器中预定义的,那么只需使用#ifdef __cplusplus ⋯ #endif就足以保证意图的正确性; 额外使用 #if __cplusplus ... #endif 反而是错误的。
仅在这种情况下:即某厂家的C语言和C++语言编译器预定义了__cplusplus,但要通过其值为0和非零来区分,使用#if __cplusplus ... #endif是正确且必要的。
由于现实世界如此复杂,你需要明确自己的目标,然后根据你的目标制定相应的策略。 例如:如果你的目标是让你的代码能够使用正确符合规范的几个主流编译器进行编译,那么你只需要简单地使用 #ifdef __cplusplus ... #endif 就足够了。
但如果你的产品是一个雄心勃勃的跨平台产品,试图兼容各种编译器(包括未知的编译器),我们可能不得不使用下面的方法来处理各种情况,其中 __ALIEN_C_LINKAGE__ 是为了识别那些定义了哪些编译器C 和 C++ 编译中的 __cplusplus 宏。
这样应该可以,但是在每个头文件中写这么长的列表不仅不美观,而且会导致策略一旦修改就会到处修改的情况。 如果你违反了DRY(不要重复自己)原则,你总是要为此付出额外的代价。 解决这个问题的一个简单解决方案是定义一个特定的头文件 - 例如 clinkage.h,并在其中添加以下定义:
在下面的示例中,c 的函数声明和定义分别位于 cfun.h 和 cfun.c 中。 该函数打印字符串“this is c fun call”。 c++的函数声明和定义分别在cppfun.h和cppfun.cpp中。 函数打印String“this is cpp fun call”,编译环境vc2010。
C++调用C方法
当c++调用c方法时,关键是以c方式编译c函数,而不是c++方式。
(1)cfun.h如下:
cppfun.cpp如下:
(2)cfun.h 同上
cppfun.cpp如下:
(3)cfun.h如下:
cppfun.cpp如下:
C调用C++方法
c调用c++,关键是C++提供了符合C调用约定的函数。
在vs2010上测试时,没有extern声明,只将cppfun.h包含在cfun.c中,然后cppfun()就可以编译运行。 但是在gcc下会出现编译错误。 该方法基于c++/c标准。 应该是错误的。 以下方法适用于两种编译器。
cppfun.h如下:
cfun.c如下:
原文链接: