D语言中的调试、版本控制和静态断言

原创 2005年03月01日 21:18:00
 

调试、版本控制和静态断言

D 支持从同一套代码构建多种版本和各种调试级别的程序,方法是使用下面的特征:
	调试说明
	调试特征
	调试语句

	版本说明
	版本特征
	版本语句

	静态断言
	DebugSpecification
	DebugAttribute
	DebugStatement

	VersionSpecification
	VersionAttribute
	VersionStatement

	StaticAssert
	

预定义版本

为了提高用法的一致性,D 预定义了几个版本标志符和标志符名字空间。版本标志符不会同代码中的其他标志符冲突,它们位于一个独立的名字空间中。预定义的版本标志符是全局的,也就是,它们可用于所有编译的和导入的模块。
DigitalMars
Digital Mars 是编译器提供商
X86
Intel 和 AMD 的 32 bit 处理器
AMD64
AMD 64 bit 处理器
Windows
Microsoft Windows 系统
Win32
Microsoft 32 bit Windows 系统
Win64
Microsoft 64 bit Windows 系统
linux
所有的 linux 系统
LittleEndian
字节序,低位优先
BigEndian
字节序,高位优先
D_InlineAsm
实现了内联汇编
none
未定义;用来禁用某段代码
如果出现了新的实现,也许会加入新的有意义的版本标志符。

D 语言无可避免地会随着时间演变。因此,以“D_”打头的版本标志符构成的名字空间被保留作为 D 语言规范或者新特征的标志的名字空间。

特定于编译器提供商的版本号可以是预定义的,形式是在提供商商标的标志符之后加上版本号,如: version(DigitalMars_funky_extension)    // DigitalMars 的有趣扩展
{
    ...
}

一定要把正确的版本号用于正确的目的。例如,在使用特定于提供商的特征时使用该提供商的标识符;在使用特定于操作系统的特征时使用该操作系统的标志符,等等。

说明

	调试说明
	    debug = 标志符 ;
	    debug = 整数 ;

	版本说明
	    version = 标识符 ;
	    version = 整数 ;
	DebugSpecification
	    debug = Identifier ;
	    debug = Integer ;

	VersionSpecification
	    version = Identifier ;
	    version = Integer ;
	
版本说明不声明符号,而是设定一个编译版本,同命令行选项 -version 的功能相同。版本说明用来支持带有版本特征和版本语句的条件编译。

版本说明调试说明 以作用于它们所在的模块。只有预定义的说明位于全局作用域,而且它们是通过命令行选项指定的。

版本说明可以以一种直接的方式将某个主版本的特征划为一组,例如:

	version (ProfessionalEdition)
	{
	    version = FeatureA;
	    version = FeatureB;
	    version = FeatureC;
	}
	version (HomeEdition)
	{
	    version = FeatureA;
	}
	...
	version (FeatureB)
	{
	    ... 实现 Feature B ...
	}
	

调试语句

通常开发人员会构建两种程序,一个发行版,一个调试版。调试版通常包括额外的错误检测代码、测试套件、友好的输出代码等。调试语句的语句体采用条件编译。这是 D中的 #ifdef DEBUG / #endif 。
	调试语句:
		调试谓词 语句
		调试谓词 语句 else 语句

	调试谓词
		debug 语句
		debug ( 整数 )
		debug ( 标志符 )
	DebugStatement:
		DebugPredicate Statement
		DebugPredicate Statement else Statement

	DebugPredicate
		debug Statement
		debug ( Integer )
		debug ( Identifier )
	
如果编译时指定了 -debug 选项,就会将调试语句编译进可执行文件内。

如果编译时指定的 -debug(n) 选项中的 n <= 整数 ,就会将 debug(整数) 语句编译进可执行文件内。

如果编译时指定的 -debug(标志符) 选项中的标志符同 标志符 匹配,就会将 debug(标志符) 语句编译进可执行文件内。

如果 语句 是语句块,则该语句块不会引入新的作用域。例如:

	int k;
	debug
	{   int i;
	    int k;	// 错误,k 已经定义了

	    i = 3;
	}
	x = i;		// 使用上面声明的 i
	

版本语句

使用一份源码生成多种不同的版本是一种通用的做法。尽管 D 可以通过将不同的版本放入不同的模块来进行版本控制,但如果仅仅更改了几行代码或整个程序就是一个模块的话,这样做就很烦人了。

	版本语句:
		版本谓词 语句
		版本谓词 语句 else 语句

	版本谓词
		version ( 整数 )
		version ( 标志符 )
	VersionStatement:
		VersionPredicate Statement
		VersionPredicate Statement else Statement

	VersionPredicate
		version ( Integer )
		version ( Identifier )
	
依据所指定的 整数 或者 标志符,采用相应的 版本语句。这两种形式都通过编译器的 -version 选项指定。如果 语句 是语句块,则各语句块不会引入新的作用域,例如:
	int k;
	version (Demo)	// 演示版会采用这块代码
	{   int i;
	    int k;	// 错误,k 已经定义了

	    i = 3;
	}
	x = i;		// 使用上面声明的 i
	
版本语句也可以通过版本特征声明选用。(译注:version=Demo; 指出采用演示版。)

版本语句可以嵌套。

如果所有的版本谓词都为假,就采用可选的 else 子句(译注:如果有的话):

	version (X86)
	{
	    ... // 实现定制的内联汇编版本
	}
	else
	{
	    ... // 使用默认的、低效的版本
	}
	
尽管调试和版本语句在表面上行为相同,但它们用于不同的目的。调试语句用来添加不应出现在发行版中的调试代码。版本语句用来加强可移植性和提供多种发行版本。

调试特征

	调试特征:
	    debug
	    debug ( 整数 )
	    debug ( 标志符 )
	DebugAttribute:
	    debug
	    debug ( Integer )
	    debug ( Identifier )
	
人们通常会构建两个版本的程序,一个发行版,一个调试版调试版包括额外的错误检查代码、试验代码、美观打印代码等。可以在编译时选择是否使用调试代码:
	class Foo
	{
		int a, b;
	    debug:
		int flag;
	}
	
条件编译 的意思是如果代码没有被采用,它仍然需要符合语法,但不会对其进行语义检查或处理。不会向符号表中添加符号,不会执行类型检查,不会生成代码,不会执行导入。可以通过给 debug 指定不同的参数来构建不同的版本:
	debug(n) { }	// 如果调试级别 <= n 就使用此代码
	debug(标志符) { } 	// 如果调试关键字是 标志符 就使用此代码
	
这等同于使用命令行参数 -debug=n-debug=标志符

版本特征

	版本特征:
	    version ( 整数 )
	    version ( 标志符 )
	VersionAttribute:
	    version ( Integer )
	    version ( Identifier )
	
版本特征同调试特征十分相似,并且在很多方面功能上相互重叠。但是它们的目的并不相同。调试特征用于构建调试版本的程序,而版本特征使用同一份源码生成多个发行版本。

例如,一个程序可能有两个版本,一个 完整版(full) ,一个 演示版(demo)

	class Foo
	{
	    int a, b;

	    version(full)
	    {
		int extrafunctionality()
		{
		    ...
		    return 1;		// 支持额外的功能
		}
	    }
	    else // demo
	    {
		int extrafunctionality()
		{
		    return 0;		// 不支持额外的功能
		}
	    }
	}
	
可以通过给 version 指定不同的参数来构建不同的版本:
	version(n) { }		// 如果版本级别 >= n 就使用此代码
	version(标志符) { } 	// 如果版本关键字是 标志符 就使用此代码
	
这等同于使用命令行参数 -version=n-version=标志符

静态断言

	静态断言:
	    static assert ( 表达式 );
	StaticAssert:
	    static assert ( Expression );
	
表达式 会在编译时计算,并转换为布尔值。如果为真,就忽略静态断言。如果为假,编译会失败,并给出错误诊断。

断言表达式 不同,静态断言 总会由编译器检查计算,除非它们出现在一个未被指定的调试或者版本语句中。

	void foo()
	{
	    if (0)
	    {
		assert(0);		// 从不执行
		static assert(0);		// 总会执行
	    }
	    version (BAR)
	    {
		static assert(0);		// 只有定义了 BAR 才会执行
	    }
	}
	
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

浏览器静态资源的版本控制新思路.强制更新指定资源缓存.的探讨

此篇,探讨的是一种可以让脚本自己更新自己缓存副本的能力. 因为上一版本,绝大多是朋友,给我的反馈是看不懂,所以我争取在这个重写的版本中.详细把每个细节都介绍一二.  如果大多数细节,都是您了解的,则跳...

互联网书籍推荐大全(编程语言,数据库,大数据,操作系统,web,版本控制)应有尽有

免费的编程中文书籍索引 免费的编程中文书籍索引,欢迎投稿。 国外程序员在 stackoverflow 推荐的程序员必读书籍,中文版。stackoverflow 上的程序员应该阅读的非编程类书籍有哪...

PHP xdebug eclipse subversion SVN phpunit xmapp 企业级团队开发环境搭建 集成单元测试 花样调试 版本控制 张迅雷原创 欢迎转载

经常在博客见到一个争论不休的话题——到底该不该学php?是学java、donet还是php?本文不讨论PHP、JSP、ASP.NET/ASP 孰优孰劣,有那功夫劲,还不如搭建个环境动手试试,毕竟存在即...

用D语言解面试题1

用D语言实现 一组数字的排列变化。 解题思路:方法1:从大到小排序后直接取两头重新组为新数组。本方法最高效。方法2:类高斯算法。本方法时间复杂度低。
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)