聊聊系统路径位置,绝对路径与相对路径,正斜杠 `/` 与 反斜杠 `\` 使用说明 ...... by 矜辰所致
目录
前段时间在写 Linux 专栏的过程中,忽然想到一个问题 :C语言的头文件路径,因为在GCC环境下面,可以很直观的了解到程序对头文件的查找位置,但是对于使用集成开发环境 KEIL 或者 IAR 的朋友们来说,一些系统的库文件路径根本就不知道在什么地方。
所以本文我们就来聊一下 C 语言的头文件路径相关的问题 ,包括系统路径位置,绝对路径与相对路径,正斜杠 / 与 反斜杠 \ 使用说明等。
我是矜辰所致,全网同名,尽量用心写好每一系列文章,不浮夸,不将就,认真对待学知识的我们,矜辰所致,金石为开!
我们都知道,在我们 C 编程的时候,我们头文件的引用使用的是 #include <> 或者 #include "",比如:

而且大家应该都知道:
这里额外提一句,因为 使用双引号" “如果在当前目录找不到头文件,最终还是会去系统路径下寻找,所以头文件包含,完全可以都使用双引号” " ,至于实际中还是有很多使用 < > 和 " " 混搭,那是因为在确定是引用系统路径的头文件的时候,使用 < > 相对来说效率高那么一点点,省去了在当前目录下面寻找的那一点时间。
对于使用双引号" " 的当前目录下查找,大家应该都知道,就是与引用头文件的.c 文件相同的目录下,比如上面是 main.c 文件引用的,就是首先在与 main.c 相同的目录中去查找。
那么对于 < > 从系统路径中搜索,这个系统目录到底在哪里呢?
我们先从我们熟悉的 IDE 入手,用 KEIL 来说明一下。
在我们使用 KEIL 做项目的时候,都需要一个IncudePaths ,就是填写头文件路径,如下图所示:
KEIL4 上是51单片机的项目:

KEIL5 上是 STM32 的项目:

为了工程结构框架,我们不可能把文件放在同一个目录下面,所以需要进行额外的指定头文件路径,这里只要用过 KEIL 的朋友应该都能明白。
对于 include 使用双引号" "的头文件,首先会在引用头文件的.c 文件相同的目录下去查找,如果查找不到,会在上面 IncudePaths 设置中所有设置过的目录中去查找,这一点我们不多赘述。
这里我们额外说明一个问题,绝对路径与相对路径。
在上面的示例图中,我们可以看到,IncudePaths 里面所添加的路径,都是 ../开头的,这种表示方式就是相对路径。
使用相对路径的好处是即便整个工程移动了位置,也无需修改什么设置,因为工程文件的相对位置没有改变。
简单复习下相对路径的表示:
./: 表示当前路径
../:表示上一级目录
绝对路径就比较简单了,绝对路径就是直接从根部(盘符)开始表示的路径,在 Windows 中,就是 C盘,D盘,这些,在 Linux 中,没有盘符的说法,根部就是 / ,比如下面两个都是绝对路径的表示:
C:\Keil\C51
/home/qzh/linux
正好提到文件路径,顺带把斜杠的问题也说一下,在上面示意图中,我们可以看到,既有正斜杠,又有反斜杠:

对于路径的表示 ( 声明,这里只是针对文件路径!路径! ):
// :/home/qzh/linux\ ,比如我们随便看一个系统显示的路径都是反斜杠 \:
\,在引用路径的时候斜杠/和反斜杠\可以互用的。比如下面两种方式的引用都是可以的:
#include "..\led\led.h"
#include "../led/led.h"
为了可移植性,引入头文件时建议使用正斜杠/ :#include "../led/led.h"
不仅如此,在Windows下引用文件路径的时候,正反双斜杠// 、\\ 与斜杠 / 、反斜杠\可以互用的,如下图所示:

双斜杠:
在写一些脚本或者程序的时候(上面是引用路径的情况,这里额外提一下程序中的情况,程序中!程序中!),我们也经常看到双斜杠,比如:
C:\\Keil\\C51
这种路径表示是为什么呢?
因为在大多编译器中,\是一个转义字符,例如\n,\r ,所以如果使用反斜杠 \,会使得路径出问题,所以会写成 \\ 。
当然正如我们上面说过的,我们在程序中可以写成 C:\\Keil\\C51 ,当然也可以使用 斜杠 / 写成C:/Keil/C51 。
额外提了那么多,回到我们的正题,来说说在 KEIL 中的 #include < > 的查找路径。
比如我们在本文第一张示意图上有一个应用#include <math.h>,我们明确的告诉编译器这个需要从系统路径中去查找,这个 KEIL 所谓的系统路径在什么地方呢?
这里我们也没什么好分析的,直接告诉大家答案:
第一个基于51平台的,使用的 51 的编译器, #include < > 的查找路径为“KEIL的安装目录”:\Keil\C51\INC ,比如博主的KEIL安装在C盘,这个路径就是C:\Keil\C51\INC:

当然,我们可以简单的做个试验确认一下,我们可以在 KEIL 中先打开 这个头文件:

然后我们打开C:\Keil\C51\INC 目录下的 MATH.h 文件,进行简单的修改,然后看一下是否是同一个文件,如下图:

那么对于 KEIL5 中的 STM32 中如果使用 #include < > ,那么这个的查找路径又是怎样的呢?
STM32 在 KEIL中使用的编译器为 ARMCC,这个系统路径的位置为:“KEIL的安装目录”:\Keil_v5\ARM\ARMCC\include ,比如博主的KEIL安装在C盘,这个路径就是C:\Keil_v5\ARM\ARMCC\include。
这一点我就不去确定了,大家可以自己添加一个库函数头文件,然后自己根据上文的方式测试一下便知。
上面介绍了 Windows 下的 KEIL 环境中的头文件系统路径,那么我们来看看 Linux 中的路径又是在哪里,我们知道在 Linux 中 C 语言的编译器是 GCC 编译器,在文章开头的前言我就写过了, 使用 GCC 编译器可以很直观的查看到 #include < > 尖括号包含的头文件的查找路径,下面我们来看一下。

写一个简单的程序,里面用到了 <stdio.h> 这个头文件,我们可以使用编译选项 -v 来打印出详细的编译步骤:

如上图所示,在 Linux 是不是很直观,没什么需要特别说明的。
那么我们再换另外一种编译器,其实还是 GCC ,只不过是 ARMGCC,我们也来看一看:

可以看到,同样的可以很直观的看到尖括号包含的头文件的搜索位置,当然,因为编译器的更换,他们搜索的位置也改变了。
最后简单总结一下,使用 #include < > 所包含的头文件,其查找路径和使用的编译器有关,编译器都会自带常用的库文件,在 GCC 环境下面,使用 -v 选项就会自动打印出查找位置,使用 IDE 环境根据 IDE 使用的编译器不同存放在对应的目录文件下面,一般来说都可以在 IDE 安装目录中可以找到。
本文我们针对 C 语言头文件路径问题进行了讲解,举例说明了 Windows 下的 IDE 环境中 和 Linux 下GCC 环境中的C语言的 头文件查找路径。
文中还对引出的绝对路径与相对路径,还有路径引用时候的 正斜杠 / 与 反斜杠 \ 与双斜杠 进行了说明。
希望大家以后在遇到头文件路径问题的时候,能够知道如何去查找问题,解决问题!
好了,本文就到这里,谢谢大家!
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信