知识若不分享 实在没有意义 http://www.d-programming-language-china.org 20070420
点击下面网址查看原文:
http://bbs.d-programming-language-china.org/thread-475-1.html
by: uFramer D语言论坛 http://www.d-programming-language-china.org
from: http://www.digitalmars.com/d/statement.html
version: 基于D 1.013 (Apr 19, 2007)
C 和 C++ 程序员将发现 D 的语句非常熟悉,他们还会发现有一些有趣的补充。
Statement:
NonEmptyStatement
ScopeBlockStatement
NoScopeNonEmptyStatement:
NonEmptyStatement
BlockStatement
NoScopeStatement:
;
NonEmptyStatement
BlockStatement
NonEmptyOrScopeBlockStatement:
NonEmptyStatement
ScopeBlockStatement
NonEmptyStatement:
LabeledStatement
ExpressionStatement
DeclarationStatement
IfStatement
ConditionalStatement
WhileStatement
DoStatement
ForStatement
ForeachStatement
SwitchStatement
CaseStatement
DefaultStatement
ContinueStatement
BreakStatement
ReturnStatement
GotoStatement
WithStatement
SynchronizedStatement
TryStatement
ScopeGuardStatement
ThrowStatement
VolatileStatement
AsmStatement
PragmaStatement
MixinStatement
Scope Statements
ScopeStatement:
NonEmptyStatement
BlockStatement
非空语句和块语句新引入了作用范围的概念。
在同函数内部,局部符号声明不能是其他局部符号声明的影子。
D语言论坛 http://www.d-programming-language-china.org 按:
影子的说法还是比较形象的。
void func1(int x)
{ int x; // 非法, x 是函数参数 x作用范围内
int y;
{ int y; } // 非法, y 掩盖了外部的y
void delegate() dg;
dg = { int y; }; // 可以, 这个y不在同函数内
struct S
{
int y; // 可以 , 这个y是成员,不是局部
}
{ int z; }
{ int z; } // 可以, 这个y没有掩盖外部的y
{ int t; }
{ t++; } // 非法, t未定义
}
主要的思想是避免在复杂函数内由于作用域声明而错误的覆盖了前面的名称造成 bug 。函数内部的所有名称都必须唯一。
Scope Block Statements
ScopeBlockStatement:
BlockStatement
A scope block statement introduces a new scope for the BlockStatement.
标号语句
语句可以有标号。标号是一种标志符,其后跟随一条语句。
LabelledStatement:
Identifier ':' NoScopeStatement
包括空语句在内的任何语句都可以有标号,因此都可以作为 goto 语句的目标。标号语句也可以用作 break 或者 continue 语句的目标。
标号位于独立的名字空间中,不与声明、变量、类型等位于同一名字空间。就算如此,标号也不能同局部声明重名。标号的名字空间是它们所在的函数体。标号的名字空间不嵌套,也就是说,一个语句块中的标号可以在语句块外访问。( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
语句块
语句块是由{ }包括起来的语句序列。其中的语句按照词法顺序执行。
语句块:
{ }
{ 语句列表 }
语句列表:
语句
语句 语句列表
BlockStatement:
{ }
{ StatementList }
StatementList:
Statement
Statement StatementList
语句块为局部符号引入了新的作用域。尽管如此,在函数内部,局部符号的名称必须唯一。
表达式语句
表达式将被计算。
表达式语句:
表达式 ;
ExpressionStatement:
Expression ;
没有作用的表达式,如 (x + x),在表达式语句中是非法的。如果有这样的需要,转换到void 就合法了。
int x;
x++; // ok
x; // illegal
1+1; // illegal
cast(void)(x + x); // ok
声明语句
声明语句声明变量和类型。( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
DeclarationStatement:
Declaration
如果没有指明 赋值表达式 来初始化变量,变量将被初始化为它的默认值。
一些声明语句:
int a; // 声明a为类型 int并初始化为0
struct S { } // 声明结构 s
alias int myint;
If 语句
If 语句提供了按条件执行语句的方法。
IfStatement:
if ( IfCondition ) ThenStatement
if ( IfCondition ) ThenStatement else ElseStatement
IfCondition:
Expression
auto Identifier = Expression
Declarator = Expression
ThenStatement:
ScopeStatement
ElseStatement:
ScopeStatement
表达式 将被计算,计算的结果必须可以被转换为布尔型。如果为 true 执行 then之后语句,否则执行 else 之后的语句。
所谓的‘悬挂 else’问题可以通过邻近匹配原则解决。
如果用了auto标识符,就被初始化和声明为表达式的值和类型。作用范围从初始化位置到then语句结束。( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
If a Declarator is provided, it is declared and initialized to the value of the Expression. Its scope extends from when it is initialized to the end of the ThenStatement.
import std.regexp;
...
if (auto m = std.regexp.search("abcdef", "b(c)d"))
{
writefln("[%s]", m.pre); // prints [a]
writefln("[%s]", m.post); // prints [ef]
writefln("[%s]", m.match(0)); // prints [bcd]
writefln("[%s]", m.match(1)); // prints [c]
writefln("[%s]", m.match(2)); // prints []
}
else
{
writefln(m.post); // error, m undefined
}
writefln(m.pre); // error, m undefined
While 语句
WhileStatement:
while ( Expression ) ScopeStatement
While 语句实现了简单的循环结构。表达式 将被计算,计算的结果必须可以被转换为布尔型。如果为 true 执行 语句 。在 语句 被执行后,将再次计算 表达式 ,如果为 true 则再次执行执行 语句 。持续这个过程直到 表达式 结果为 false 。
int i = 0;
while (i < 10)
{
foo(i);
i++;
}
break 语句将退出循环。continue 语句将直接跳转到下一次计算 表达式 。
Do-While 语句
DoStatement:
do ScopeStatement while ( Expression )
Do-While 语句实现了简单的循环结构。
表达式 首先被执行。然后计算 表达式 ,结果必须可以被转换为布尔型。如果结果为 true 继续循环,直到 表达式 的值变为 false 。
int i = 0;
do
{
foo(i);
} while (++i < 10);
break 语句将推出循环。continue 语句将直接进行下一轮 表达式 估值。( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
For 语句
For 语句实现了带有初始化、测试和递增的循环结构。
ForStatement:
for (Initialize Test; Increment) ScopeStatement
Initialize:
;
NoScopeNonEmptyStatement
Test:
empty
Expression
Increment:
empty
Expression
先执行 初始化 。然后计算 测试 ,结果必须可以被转换为布尔型。如果结果为 true ,执行 语句 。在执行 语句 后,将执行 递增 。然后再次计算 测试 ,如果结果为 true 再次执行 语句 。持续这个过程直到 测试 的计算结果为 false 。
break 语句将退出循环。continue 语句将直接跳转到 递增 。
for语句创建了一个作用域,如果 初始值 声明了一个变量,变量的作用域持续到 语句 结束。例如:
for (int i = 0; i < 10; i++)
foo(i);
等价于:
{ int i;
for (i = 0; i < 10; i++)
foo(i);
}
函数体不能为空:
for (int i = 0; i < 10; i++)
; // 非法
正确的写法是:
for (int i = 0; i < 10; i++)
{
}
初始值 可以忽略。测试 也可以被忽略,如果忽略,就假定为 true 。
Foreach 语句
foreach 语句遍历一个聚集的全部内容
A foreach statement loops over the contents of an aggregate.( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
ForeachStatement:
Foreach (ForeachTypeList; Aggregate) ScopeStatement
Foreach:
foreach
foreach_reverse
ForeachTypeList:
ForeachType
ForeachType , ForeachTypeList
ForeachType:
ref Type Identifier
Type Identifier
ref Identifier
Identifier
Aggregate:
Expression
Tuple
先计算 聚集 的值。它的结果必须为静态数组、动态数组、关联数组、结构,类,委托或者tupe。对于聚集表达式的每个元素执行一次 语句 。在每次遍历开始时,Foreach类型列表 声明的变量默认为聚集的内容的拷贝(即采用传值方式)。如果变量是 ref的,这些变量就是聚集内容的引用(即采用传引用方式)。
The aggregate must be loop invariant, meaning that elements to the aggregate cannot be added or removed from it in the NoScopeNonEmptyStatement.
如果聚集表达式是静态或动态数组,可以声明一个或者两个变量。如果声明了一个变量,那么这个变量就被赋予数组元素的 值 ,一个接一个。变量的类型必须同数组内容的类型匹配,除了下面提到的特殊情况以外。如果声明了两个变量,第一个变量对应于 索引 ,第二个对应于 值 。索引 必须是 int 或者 uint 类型,它不能是 ref 的,它的值是数组元素的索引。
char[] a;
...
foreach (int i, char c; a)
{
printf("a[%d] = '%c'\n", i, c);
}
For foreach, the elements for the array are iterated over starting at index 0 and continuing to the maximum of the array. For foreach_reverse, the array elements are visited in the reverse order.
如果聚集表达式是 char、wchar 或者 dchar 的静态或动态数组,则 值 的 类型 可以是 char、wchar 或 dchar 中的任何一个。采用这种方式,任何 UTF 数组可以被解码为任何 UTF 类型:( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
char[] a = "\xE2\x89\xA0"; // \u2260 编码为 3 个 UTF-8 byte
foreach (dchar c; a)
{
printf("a[] = %x\n", c); // 打印 'a[] = 2260'
}
dchar[] b = "\u2260";
foreach (char c; b)
{
printf("%x, ", c); // 打印 'e2, 89, a0'
}
聚集可以是字符串文字量,这样的聚集可以看作 char、wchar 或 dchar 数组来访问:
void test()
{
foreach (char c; "ab")
{
printf("'%c'\n", c);
}
foreach (wchar w; "xy")
{
wprintf("'%c'\n", w);
}
}
将打印出:
如果聚集表达式是关联数组,可以声明一个或者两个变量。如果声明了一个变量,那么这个变量就被赋予数组元素的 值 ,一个接一个。变量的类型必须同数组内容的类型匹配。如果声明了两个变量,第一个变量对应于 索引 ,第二个对应于 值 。索引 必须同关联数组的索引具有相同的类型,它不能是 ref ,它的值是数组元素的索引。数组元素的顺序是未指定的,foreach_reverse用于关联数组是非法的。
double[char[]] a; // 索引 类型是 char[],值 类型是 double
...
foreach (char[] s, double d; a)
{
printf("a['%.*s'] = %g\n", s, d);
}
如果聚集是一个结构或者类对象,则它由特定opApply 成员函数定义,foreach_reverse行为由特定opApplyReverse成员函数定义,这此函数定义的类型必须和foreach语句相一致。函数具有类型:
int opApply(int delegate(ref Type [, ...]) dg);
int opApplyReverse(int delegate(ref Type [, ...]) dg);
其中 Type 要同 foreach 声明中 标志符 中的 类型 匹配。
传递给 opApply 的委托类型中剩下的那些 类型 (上式中的“...”)对应于其余的多个 Foreach类型 。
结构或类中可以有多个不同的 opApply 函数,foreach语句 会使用类型匹配的函数,该函数的参数 dg 的参数类型要同 foreach语句 中对应的 Foreach类型 匹配。opApply 的函数体遍历聚集的元素,并将它们作为参数依次传递给 dg 函数。如果 dg 返回 0 ,则 opApply 继续应用于下一个元素。如果 dg 返回一个非零值,opApply 必须停止遍历并返回那个值。如果 opApply 顺利遍历了所有的元素,会返回 0 。( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
例如,考虑包含两个元素的容器类:
class Foo
{
uint array[2];
int opApply(int delegate(ref uint) dg)
{ int result = 0;
for (int i = 0; i < array.length; i++)
{
result = dg(array);
if (result)
break;
}
return result;
}
}
一个可能的例子是:
void test()
{
Foo a = new Foo();
a.array[0] = 73;
a.array[1] = 82;
foreach (uint u; a)
{
printf("%d\n", u);
}
}
将打印出:
If Aggregate is a delegate, the type signature of the delegate is of the same as for opApply. This enables many different named looping strategies to coexist in the same class or struct.
ref can be used to update the original elements:( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
void test()
{
static uint[2] a = [7, 8];
foreach (ref uint u; a)
{
u++;
}
foreach (uint u; a)
{
printf("%d\n", u);
}
}
which would print:
ref can not be applied to the index values.
If not specified, the Types in the ForeachType can be inferred from the type of the Aggregate.
在 foreach 遍历所有数据项时,不能修改聚集本身,不能重新设定聚集大小、重新分配、释放、重新赋值或析构。
int[] a;
int[] b;
foreach (int i; a)
{
a = null; // 错误
a.length += 10; // 错误
a = b; // 错误
}
a = null; // ok
If the aggregate is a tuple, there can be one or two variables declared. If one, then the variable is said to be the value set to the elements of the tuple, one by one. If the type of the variable is given, it must match the type of the tuple contents. If it is not given, the type of the variable is set to the type of the tuple element, which may change from iteration to iteration. If there are two variables declared, the first is said to be the index and the second is said to be the value. The index must be of int or uint type, it cannot be ref, and it is set to be the index of the tuple element.( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
If the tuple is a list of types, then the foreach statement is executed once for each type, and the value is aliased to that type.
import std.stdio;
import std.typetuple; // for TypeTuple
void main()
{
alias TypeTuple!(int, long, double) TL;
foreach (T; TL)
{
writefln(typeid(T));
}
}
打印出:
如果在 foreach 体内有 Break语句 ,则会退出 foreach ,而 Continue语句 将立即开始下一轮遍历。
Switch 语句
switch 语句依照 switch 表达式的值来选择一条 case 语句执行。
SwitchStatement:
switch ( Expression ) ScopeStatement
CaseStatement:
case ExpressionList : Statement
DefaultStatement:
default: Statement
表达式 被计算. 结果的类型 T 必须是整数类型或者 char[] wchar[] 或者 dwchar[] 。所得结果同各个 case 表达式进行比较。如果存在匹配,就转而执行相应的 case 语句。
case 表达式,也就是 表达式列表 ,是由逗号分隔的表达式的列表。( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
如果没有 case 表达式能够匹配,并且存在 default 语句,就转去执行 default 语句。
如果没有 case 表达式能够匹配,并且不存在 default 语句,就会抛出 SwitchError 异常。之所以这么做,是为了捕获一些常见的错误,如为枚举添加了新值却忘记了为这个值提供对应的 case 语句。这同 C 和 C++ 不太一样。( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
case 表达式必须都是常量值或数组,并且必须能隐式地转换为 switch 表达式 的类型 T。
Case 表达式的值必须互不相同。不能有多于一个的 default 语句。
与 switch 相关联的 case 语句和 default 语句可以在语句块中嵌套;它们不必非要位于最外层的块中。例如,下面是合法的:( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
switch (i)
{
case 1:
{
case 2:
}
break;
}
同在 C 和 C++ 中一样,case 语句会顺序执行后面的 case 子句。break 语句将退出 switch 语句块。例如:
switch (i)
{
case 1:
x = 3;
case 2:
x = 4;
break;
case 3,4,5:
x = 5;
break;
}
如果 i 等于 1,x 将等于 5 。
注意:同 C 和 C++ 不同的是,可以在 switch 表达式中使用字符串。例如:
char[] name;
...
switch (name)
{
case "fred":
case "sally":
...
}
对于如命令行选项处理这样的应用来说,采用这种语法的代码更直接,更清晰并且不易出错。ascii 和 wchar 都可以使用。
实现注意:编译器的代码生成程序可以认为 case 语句已经按照使用的频率排序,频率高的排在最前面,频率低的排在最后。尽管这不会影响程序的正确性,但对于提高性能来说是有益的。
Continue 语句
continue 中止它所在的循环语句的此次迭代,并直接开始下次迭代。( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
Continue语句:
continue;
continue 标志符 ;
ContinueStatement:
continue;
continue Identifier ;
continue 执行它所在最内层的 while、for 或者do 语句的下次迭代。
如果 continue 后跟有 标志符 ,则该 标志符 必须是它所在的 while、for 或者 do 语句外的标号,continue 会执行所在循环的下次迭代。如果不存在那样的语句,就是错误。
所有的被跳过的 finally 子句都会执行,同时会释放所有的被跳过的同步对象。(译注:目前未实现。)
注意:如果 finally 子句中有 return、throw 或者 goto 到 finally 子句之外的这样的动作,continue 的目标永远也无法达到。
for (i = 0; i < 10; i++)
{
if (foo(i))
continue;
bar();
}
Break 语句
break 退出它所在的语句。
Break语句:
break;
break 标志符 ;
BreakStatement:
break;
break Identifier ;
break 退出它所在最内层的 while、for、do 或者 switch 语句,并在该语句之后恢复执行。
如果 break 后跟有 标志符 ,则该 标志符 必须是它所在的 while、for、do 或者 switch 语句外的标号,break 会退出那条语句。如果不存在那样的语句,就是错误。( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
所有的被跳过的 finally 子句都会执行,同时会释放所有的被跳过的同步对象。(译注:目前未实现。)
注意:如果 finally 子句中有 return、throw 或者 goto 到 finally 子句之外的这样的动作,break 的目标永远也无法达到。
for (i = 0; i < 10; i++)
{
if (foo(i))
break;
}
Return 语句
Return语句:
return;
return 表达式 ;
ReturnStatement:
return;
return Expression ;
return 语句的作用是退出当前的函数并提供一个返回值。如果函数指定了非 void 的返回类型,就必须给出 表达式 。表达式 会被隐式地转换为函数的返回类型。
如果函数指定了非 void 的返回类型,就必须提供至少一个 return 语句 或者assert(0)表达式。
就算函数的返回类形是 void,也可以有 表达式 存在。表达式 会被计算,但是什么也不会返回。
在函数真正返回之前,所有自动保存持续的对像被毁坏,会执行所有外围的 finally 子句,所有scope(exit)语句被执行,所有scope(sucess)语句被执行,并会释放外围的所有同步对象。( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
如果外围的 finally 子句中有 return、goto 或者 throw 的话,函数就不会正常的返回。
如果存在后验条件(参见契约式编程),则在计算 表达式 之后执行该后验条件,然后函数返回。
int foo(int x)
{
return x + 3;
}
Goto 语句
Goto语句:
goto 标志符 ;
goto default ;
goto case ;
goto case 表达式 ;
GotoStatement:
goto Identifier ;
goto default ;
goto case ;
goto case Expression ;
goto 会跳转到以 标志符 为标号的语句处运行:
if (foo)
goto L1;
x = 3;
L1:
x++;
第二种形式,goto default; ,会跳转到最内层 Switch语句 中的 Default语句 处。
第三种形式,goto case; ,会跳转到最内层 Switch语句 中的下一个 Case语句 处。
第四种形式,goto case 表达式; ,会跳转到包含带有 表达式 的 Case语句 的最内层 Switch语句 中那个 Case语句 处。( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
switch (x)
{
case 3:
goto case;
case 4:
goto default;
case 5:
goto case 4;
default:
x = 4;
break;
}
所有的被跳过的 finally 子句都会执行,同时会释放所有的被跳过的同步互斥体。(译注:目前未实现。)
使用 goto 来跳过初始化是非法的。
With 语句
WithStatement:
with ( Expression ) ScopeStatement
with ( Symbol ) ScopeStatement
with ( TemplateInstance ) ScopeStatement
with 语句用来简化对同一个对象的重复引用。 表达式 的结果是对类实例或者结构的引用。在 with 的过程体内,所有的标志符符号都将在那个类引用的名字空间内查找。with 语句:
with (expression) { ... ident; } 在语义上等价于:
{
Object tmp;
tmp = expression;
...
tmp.ident;
}
注意表达式只会计算一次。with 语句不会改变 this 或 super 引用的对象。( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
For Symbol which is a scope or TemplateInstance, the corresponding scope is searched when looking up symbols. For example:
struct Foo
{
typedef int Y;
}
...
Y y; // error, Y undefined
with (Foo)
{
Y y; // same as Foo.Y y;
}
Synchronize 语句
synchronize 语句用来在多线程情况下同步临界区内的语句。
SynchronizedStatement:
synchronized ScopeStatement
synchronized ( Expression ) ScopeStatement
synchronized 每次只允许一个线程执行 语句。
在 synchronized (表达式) 这种用法中,表达式 的结果应为对一个 Object 对象的引用,它每次只允许在一个线程中的那个 Object 执行 语句。如果表达式是接口实例,就转换为对象。
当 语句 遇到异常、goto 或者 return 中止时,同步中止,goto 或者return。
示例:
这实现一个标准的临界区。
Try 语句
异常处理由 try-catch-finally 语句完成。
TryStatement:
try ScopeStatement Catches
try ScopeStatement Catches FinallyStatement
try ScopeStatement FinallyStatement
Catches:
LastCatch
Catch
Catch Catches
LastCatch:
catch NoScopeNonEmptyStatement
Catch:
catch ( CatchParameter ) NoScopeNonEmptyStatement
FinallyStatement:
finally NoScopeNonEmptyStatement
CatchParameter 声明了类型为 T 的变量 v ,其中 T 是 Object 或者从 Object 派生而来。如果 T 与 throw 表达式类型相同或者是 throw 表达式的基类,v 被初始化为 throw 表达式。如果异常对象是 T 型或者从 T 派生的,catch 子句将被执行。
如果只给出了类型 T 而没有给出变量 v ,catch 子句仍将被执行。
如果有类型为 T1 的 CatchParameter 参数 掩盖了后面的类型为 T2 的 Catch ,也就是说如果 T1 同 T2 类型相同或者是 T2 的基类,就是错误。
LastCatch 捕获所有的异常。( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
FinallyStatement 总是被执行,即使try ScopeStatement存在goto,break,continue,return,exception,或者fall-throuth。
如果在FinallyStatement引发异常,而且没有在 FinallyStatement执行前被捕捉到,新的异常会替换已经存在的异常。
int main()
{
try
{
try
{
throw new Exception("first");
}
finally
{
printf("finally\n");
throw new Exception("second");
}
}
catch(Exception e)
{
printf("catch %.*s\n", e.msg);
}
printf("done\n");
return 0;
}
将打印出:
finally
catch second
done
A FinallyStatement may not exit with a goto, break, continue, or return; nor may it be entered with a goto.
A FinallyStatement may not contain any Catches. This restriction may be relaxed in future versions.( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
Throw 语句
抛出一个异常。
Throw语句:
throw 表达式 ;
ThrowStatement:
throw Expression ;
表达式 被计算,结果必须是 Object 引用类型。该 Object 的引用被作为异常抛出。
throw new Exception("message");
Scope Guard Statement
ScopeGuardStatement:
scope(exit) NonEmptyOrScopeBlockStatement
scope(success) NonEmptyOrScopeBlockStatement
scope(failure) NonEmptyOrScopeBlockStatement
The ScopeGuardStatement executes NonEmptyOrScopeBlockStatement at the close of the current scope, rather than at the point where the ScopeGuardStatement appears. scope(exit) executes NonEmptyOrScopeBlockStatement when the scope exits normally or when it exits due to exception unwinding. scope(failure) executes NonEmptyOrScopeBlockStatement when the scope exits due to exception unwinding. scope(success) executes NonEmptyOrScopeBlockStatement when the scope exits normally.
If there are multiple ScopeGuardStatements in a scope, they are executed in the reverse lexical order in which they appear. If any auto instances are to be destructed upon the close of the scope, they also are interleaved with the ScopeGuardStatements in the reverse lexical order in which they appear.
writef("1");
{
writef("2");
scope(exit) writef("3");
scope(exit) writef("4");
writef("5");
}
writefln()
写出:12543
{
scope(exit) writef("1");
scope(success) writef("2");
scope(exit) writef("3");
scope(success) writef("4");
}
writefln();
写出: 4321
class Foo
{
this() { writef("0"); }
~this() { writef("1"); }
}
try
{
scope(exit) writef("2");
scope(success) writef("3");
auto Foo f = new Foo();
scope(failure) writef("4");
throw new Exception("msg");
scope(exit) writef("5");
scope(success) writef("6");
scope(failure) writef("7");
}
catch (Exception e)
{
}
writefln();
写出: 0412
A scope(exit) or scope(success) statement may not exit with a throw, goto, break, continue, or return; nor may it be entered with a goto.
Volatile 语句
没有什么代码活动能跨越 volatile 语句的边界。
VolatileStatement:
volatile Statement
volatile ;
语句 被计算。在 语句 之前的所有内存写操作都保证在 语句 中或其后的内存读操作之前完成。在 语句 之后的所有内存读操作都保证在 语句 中或其前的所有内存写完成之后执行。
volatile 语句不能保证原子性。如果要保证原子性,应该使用 synchronized 语句。
Asm 语句
asm 语句用来支持内联汇编:
Asm语句:
asm { }
asm { Asm指令列表 }
Asm指令列表:
Asm指令 ;
Asm指令 ; Asm指令列表
AsmStatement:
asm { }
asm { AsmInstructionList }
AsmInstructionList:
AsmInstruction ;
AsmInstruction ; AsmInstructionList
asm 语句使你可以直接使用汇编语言指令。这样不必费力地采用外部的汇编程序就可以获得对CPU特殊特征的直接访问能力。D 编译器会替你管理函数调用约定、堆栈设置等等恼人的事情。
指令的格式,当然,高度依赖于目标CPU的指令集,所以是由 实现定义 的。但是,格式需要遵循下述约定:( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
必须使用同 D 语言相同的记号。
注释的形式必须同 D 语言的相通。
Asm 指令以‘;’结尾,而不是以行尾结尾。
这些规则保证 D 的源代码可以独立于语法或语义分析而被记号化。
例如,对于 Intel Pentium 处理器:
int x = 3;
asm
{
mov EAX,x; // 将 x 载入寄存器 EAX
}
内联汇编可以用来直接访问硬件:
int gethardware()
{
asm
{
mov EAX, dword ptr 0x1234;
}
}
对于某些 D 实现,如将 D 翻译为 C 的翻译器来说,内联汇编没有什么意义,也就不需要实现它。version 语句可以用来应付这种情况:
version (D_InlineAsm_X86)
{
asm
{
...
}
}
else
{
/* ... some workaround ... */
}
Pragma Statement
PragmaStatement:
Pragma NoScopeStatement
Mixin Statement
MixinStatement:
mixin ( AssignExpression ) ;
The AssignExpression must evaluate at compile time to a constant string. The text contents of the string must be compilable as a valid StatementList, and is compiled as such.( 本文出处: http://bbs.d-programming-language-china.org/thread-475-1.html )
void main()
{
int j;
mixin("
int x = 3;
for (int i = 0; i < 3; i++)
writefln(x + i, ++j);
"); // ok
const char[] s = "int y;";
mixin(s); // ok
y = 4; // ok, mixin declared y
char[] t = "y = 3;";
mixin(t); // error, t is not evaluatable at compile time
mixin("y =") 4; // error, string must be complete statement
mixin("y =" ~ "4;"); // ok
}
( lastupdate:20070421 最新文章请访问http://www.d-programming-language-china.org )关于一大步成功社区:
yidabu提倡在交流中学习,在分享中提高
收集感兴趣的知识,写下心得,通过网络与别人一起分享
理解一点就实践一步,收获什么就分享什么,成功就是这样一点点一步步累积起来的
网络只是一个工具,只有自己身心提高才是实实在在的。d-programming-language-china.org为大家提供一个学习交流各种知识的平台