前面说过,本系列文章的前提是您懂C语言,懂面向对象中的一些概念,如果没有任何变成基础,从零开始学习D语言将是一个漫长的过程,因为很多概念都要重新诠释,让一个没有基础的人经过漫长的学习过程,然后还找不到工作,这显然是在坑人,所以我的思路是让有编程经验的人先了解D语言,用D语言,使D语言为更多的项目所用,从而创造出工作机会,然后再让新入行的人开始学习。好了,言归正传,开始我们今天的学习之旅
 

先来熟悉下编译器 DMD

首先我先带大家从0开始,成功的编写的一D语言程序,然后编译并运行起来,再介绍一些常用的选项。这部分不是要介绍一个hello world程序如何写,因为第一篇文章中已经有了4个版本,而是要向读者们介绍D语言的编译器的使用,关于编译器有哪些以及在哪下载前面文章中已经介绍,不再叙述,安装也都很简单,无论是在哪个系统下,和其它软件的安装也没什么区别,从现在开始假设您已经安装好了DMD(至于GDC的使用,由于属于GCC家族,所以它跟GCC的使用基本上是一致的,只是有些D语言特有的选项)
 
dmd 编译器的使用所有平台都是一样的,以下使用 $作为命令提示符,对于不了解 *nix 系统的用户需要注意
通过dmd —help 可以查看所有选项
 
1、最基本的编译命令
$ dmd xx.d
如果编译成功,会生成两个文件,一可执行文件 xx.o 另一个是链接后的可执行文件 xx (Windows 下对应的文件为 xx.obj 和 xx.exe)
 
2、如何指定生成的文件名(不是编译完了再改名)
$dmd -ofmain xx.d
这样就可以生成 main 和main.o,注意 -of和文件名之间不能有空白,是连续的
 
3、如果不希望生成 .o 或者 .obj 文件,可以使用额外参数 -o- ,o前后各一个减号。这个选项的设计也是有点意思
如果想要把 obj 文件指定到别的目录,可以使用 -odobjdir 参数,如:
 
$ dmd -odobjs -ofmain xx.d
将 obj  文件存放到 objs 目录中,同样,目录名和-od是连续的
 
4、我们知道,D语言是使用GC的,dmd提供一个选项 -vgc 可以在编译过程中输出,哪些地方使用了GC管理内存,如果没有输出,表示没有使用GC
$ dmd -vgc xx.d
 
5、直接运行源文件,dmd提供了两种方法可以做到这一点
$ dmd -run xx.d
$ rdmd xx.d
其中rdmd是一个单独的程序,如果是 *nix 系统还可以使用 #!/usr/bin/env rdmd 这样的方式,把rdmd做为D源代码的解释器(别忘了给源文件加可执行权限)
 
两种方式的工作方式是类似的,都是先将源代码编译,然后执行,区别是 dmd -run 是将生成的文件放在当前目录,运行后删除了生成的可执行文件,而rdmd则是将生成的可执行文件放到了临时目录,运行后不删除,如果没有修改源代码,则直接运行上次生成的文件,不会重新编译,所以第一次会比较慢,以后就非常快了(因为只是比直接执行多了一步判断源代码是否被修改),这种特性使D语言可以做为脚本语言来使用,虽然原理与脚本不同,但使用起来跟脚本一样,而dmd -run 由于删除了生成的可执行文件,所以每次都要重新编译
上面这段描述如果只是按我说的记住的话,这是死记,不推荐,我所推荐的学习方式是要多实践,在实践中去验证,这样记忆会更深刻,学习效果也更好
其实这很好验证,写一个简单的程序即可
 
import std.stdio;
void main(string[] args)
{
writeln(args);// 输出命令行参数,通过这个方法很容易知道我们的程序是如何启动的
}
 
分别使用 dmd -run 和 rdmd来运行这个程序,很容易能发现区别,以及rdmd生成的文件具体在哪,和如何通过某哈希算法确定源文件是否被修改。
请读者朋友亲自在自己的系统上测试,这里我就不给出我的运行结果了
如果你觉得这没什么也很正常,也确实没什么,只是一个方便的小工具而已。即使没有写一个也不是啥难事,不过D的源文件第一行可以忽略#! 开始的内容,应该说是一个很贴心的设计
 

大跃进开始

  细心的读者可能发现,上面的小程序中的 string[] args 似乎在传达着一个信息,D语言中的字符串和数组好像比C/C++的有着更高级的特性,没错,D的字符串和数组的确要比C/C++中的要高级,D不仅支持变长的数组,还支持关联数组,这会在很大程度上加快开发效率,可以想像下如果PHP没有了关联数组,Python没有了字典,它还能那么方便吗,不过很遗憾,我并不想在这篇文章中介绍D中的数组,在学习高级数据类型前我们应该先学习基本数据类型,D语言的基本类型也没有那么特别,如果你熟悉C语言,大多数只要看见类型的关键字就能理解它的意思
D的基本类型有:
void、bool、byte、ubyte、short、ushort、int、uint、long、ulong、cent、ucent、float、double、real、ifloat、idouble、ireal、cfloat、cdouble、creal、char、wchar、dchar
看上去很多,不过有些不需要解释,一看就知道是什么意思,但有些不一定能看的出来,因为其它语言中几乎看不到这样的类型,下面对于不容易理解的做出解释
 
cent、ucent 为128整数,不过目前还没有实现,所以在程序中不可用,但是它是保留的关键字
real 为80位浮点实现
前缀为i的类型为虚数类型,字面量为加上i后缀的形式,如: ifloat x = 1.23i;
前缀为c的为复数类型,字面量为实数+虚数,如:cfloat x = 2.3 + 3.5i;
注:如果你不知道什么是虚数和复数,那只能说你数学不好,该补补数学了,其它语言多数是由库来实现的,但是如果由语言来实现看起来更自然,用起来也便简洁
char,wchar,dchar的区别分别是 UTF-8 8位,UTF-16 16位,UTF-32 32位,都是无符号的,字符语义,而byte是的数值语义
所以D语言支持多字节的字符,如:wchar wc = ‘我’; dchar dc = ‘你’;
如果您还记得前面文章中提到的D语言的源文件编码必须是UTF-8,UTF-16,UTF-32,可能会有这样的疑惑,汉字的UTF-8编码占三个字节,那UTF-8编码的源文件中的汉字字面量不是要占三个字符,怎么能存到wchar 16位中呢。如果是按源文件是什么就存什么的原则肯定是不行的,这里编译器会将UTF-8的编码转换成UTF-16的编码,然后再赋值,同理,虽然UTF-32是四个字节,足以容纳3个字节的汉字,但既然规定了dchar是UTF-32编码,就会将其转换成UTF-32,而不是直接存UTF-8的编码数据。如果您对编码不熟悉,可能不能很好的理解这段叙述,建议您去找下关于字符编码方面的资料学习一下,再回来看
 
对于字节序,D语言是CPU相关的,这点上和Java不同,做为一个系统编程语言这点我觉得有必要指出,不清楚字节序是什么的建议找下相关资料
 
由于D语言中的基本数据类型并不特别,能兼容C中的所有数据类型,所以在与C交互的时候也不需要特别的处理,直接找到对应的类型用即可,也许你不觉得这是优点,觉得就应该是这个样子的,那你对比下Go和Rust的做法就会发现,它们的做法也是醉了
 
关于默认初始化,D中的变量都会默认初始化为类型的默认值,整数类通常是0,但需要注意的是浮点变量的初始值是 类型.nan, 如 float.nan;
字符型 char,wchar,dchar 分别是 0xFF,0xFFFF,0x0000FFFF,并且所有的类型数据的初始值都可以用 类型.init 来表示,如果你有兴趣可以写个小程序测试下,如: writeln(int.init),writeln(wchar.init) 等
因为初始化是一个赋值过程,所以 int a; 与 int a = int.init;是等价的,所以初始化过程一样会进行内存的拷贝,虽然代价是非常小的,但有的时候为了效率我们不希望初始化,也不需要初始化,那怎么办呢,做为兼顾效率和高级特性的语言,是允许不默认初始化的。D语言使用 int a = void;这种形式来让变量不进行默认的初始化,即用void初始化等于不初始化,如果你真的需要这么做的话
 
对于运算符,C中的运算符在D里面都可以用,而且优先级是一样的,所以这里就不列出所有的运算符了,不过D里面还有一些其它的运算符,这些运算符会在后面的文章中介绍,因为它们是一些高级特性所需要的运算符
 
最后说下D语言的main函数,这个函数不需要返回值,所以返回类型为void,熟悉C语言的朋友都知道,C里面main的返回值是程序退出时的代码,通常表示程序的结果是否出错,那D没有返回值怎么表示出错呢,D是通过现代语言中流行的异常处理的方式来做的,所以也就不需要返回一个整数了。从程序启动的角度说,C程序的main函数是由 C runtime的启动代码调用的,而D的main函数是被C的main函数调用的,只不过调用D的main函数前要初始化D runtime,通过 rt_init 函数,完了再调用,rt_term,(可能还有一些其它的代码,我没看源码,也不好说)这在第一篇Hello World程序中已经用过
 
另外D语言中流程控制语句和函数也是兼容C的,所以到目前为止,您已经掌握了很多关于D语言的很多知识了
基本类型
函数的定义与调用(D还支持委托,闭包,纯函数等后面会介绍,目前先当C的函数用就行)
运算符
流程控制语句(D还有一些高级流程控制语句,后面会介绍)
调用C函数(C函数包括C标准库、自定义函数、和系统调用或叫系统API)
所以到目前为止,您用它来写一些练习小程序应该完全没有问题了,如一些小算法练习,一些简单的C的API调用
不过到目前位置,我们所学到的D语言只不过是C语言的代替品,语法上也基本一致,还体现不出D语言的强大之处,但不要因为这个原因而不练习,成功的经验会增加你后续学习的信心,在练习的过程中还可能会发现一些细节上的不同

《玩转D语言系列》三、轻松大跃进,把它当C语言先用起来的更多相关文章

  1. Go语言系列(三)之数组和切片

    <Go语言系列文章> Go语言系列(一)之Go的安装和使用 Go语言系列(二)之基础语法总结 1. 数组 数组用于存储若干个相同类型的变量的集合.数组中每个变量称为数组的元素,每个元素都有 ...

  2. 《玩转D语言系列》二、D语言现状、基本规定和相关资源介绍

    这算是本系列文章的一个序吧,主要是为以后的学习做铺垫,文本分为三个部分,第一部分是对于网上一些比较旧的资料的问题的一些更正,当然我也不可能看过所有的资料,难免会有遗漏.第二部分是D语言最基本的规定,第 ...

  3. 使用 PySide2 开发 Maya 插件系列三:qt语言国际化(internationalization)

    使用 PySide2 开发 Maya 插件系列三:qt语言国际化(internationalization) 前言: 这是 qt for python 的语言国际化,基于 UI 的,python 也有 ...

  4. 完毕port(CompletionPort)具体解释 - 手把手教你玩转网络编程系列之三

       手把手叫你玩转网络编程系列之三    完毕port(Completion Port)具体解释                                                    ...

  5. Go语言系列:(1)在VsCode中配置Go的开发环境

    一.为什么选VSCode 这个系列的初宗是带领公司的PHPer转Go,在正式写这篇博文前,咱们先说说Go有哪些主流的IDE 1.GoLand(收费) JetBrains出品必属精品,除了贵没有其它缺点 ...

  6. 玩转大数据系列之Apache Pig高级技能之函数编程(六)

    原创不易,转载请务必注明,原创地址,谢谢配合! http://qindongliang.iteye.com/ Pig系列的学习文档,希望对大家有用,感谢关注散仙! Apache Pig的前世今生 Ap ...

  7. 玩转Windows服务系列——使用Boost.Application快速构建Windows服务

    玩转Windows服务系列——创建Windows服务一文中,介绍了如何快速使用VS构建一个Windows服务.Debug.Release版本的注册和卸载,及其原理和服务运行.停止流程浅析分别介绍了Wi ...

  8. 玩转Windows服务系列——Debug、Release版本的注册和卸载,及其原理

    Windows服务Debug版本 注册 Services.exe -regserver 卸载 Services.exe -unregserver Windows服务Release版本 注册 Servi ...

  9. 玩转Windows服务系列——创建Windows服务

    创建Windows服务的项目 新建项目->C++语言->ATL->ATL项目->服务(EXE) 这样就创建了一个Windows服务项目. 生成的解决方案包含两个项目:Servi ...

随机推荐

  1. log4php的配置

    网上关于log4php配置的文章很多,下面是我的配置,跟网上部分略有不同 (1)添加日志     1.下载log4php,到官网就可以下载到,下载后解压     我的版本是log4php_2.3.0 ...

  2. 【DP】HDU 1176

    HDU 1176 免费馅饼 题意:中文题目不解释. 思路:因为是从中间出发所以思路卡了许久,还在之前做了道HIHO入门的题.能想到的点,从时间思考,然后初始化1s的时候,4,5,6,的数值要特别赋值. ...

  3. View基础知识

    一.View基础知识 View 是Android中所有控件的基类,是一种界面层的控件的一种抽象,代表了一个控件 1.View的位置参数 View的四个属性:top(左上角纵坐标)     left(左 ...

  4. 水坑式攻击-APT攻击常见手段

    所谓“水坑攻击”,是指黑客通过分析被攻击者的网络活动规律,寻找被攻击者经常访问的网站的弱点,先攻下该网站并植入攻击代码,等待被攻击者来访时实施攻击. 水坑攻击属于APT攻击的一种,与钓鱼攻击相比,黑客 ...

  5. 李洪强iOS经典面试题144-数据存储

    李洪强iOS经典面试题144-数据存储   数据存储 sqlite中插入特殊字符的方法和接收到处理方法. 除'其他的都是在特殊字符前面加"/",而 ' -> '' .方法:k ...

  6. java中强制类型转换

    在Java中强制类型转换分为基本数据类型和引用数据类型两种,这里我们讨论的后者,也就是引用数据类型的强制类型转换. 在Java中由于继承和向上转型,子类可以非常自然地转换成父类,但是父类转换成子类则需 ...

  7. Ubuntu换源

    转自: http://wiki.ubuntu.org.cn/index.php?title=Qref/Source&variant=zh-cn 不同的网络状况连接以下源的速度不同, 建议在添加 ...

  8. java并发控制:lock

    一.synchronized的缺陷 synchronized是java中的一个关键字,也就是说是Java语言内置的特性.那么为什么会出现Lock呢? 在上面一篇文章中,我们了解到如果一个代码块被syn ...

  9. Android课程---添加黑名单的练习(课堂讲解)

    DBHelper.java package com.hanqi.test3; import android.content.Context; import android.database.sqlit ...

  10. Nginx 和 Apache 开启目录浏览功能

    1.Nginx 在相应项目的 Server 段中的 location 段中,添加 autoindex on.例如: server { listen ; server_name www.dee.prac ...