Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1299714
  • 博文数量: 554
  • 博客积分: 10425
  • 博客等级: 上将
  • 技术积分: 7555
  • 用 户 组: 普通用户
  • 注册时间: 2006-11-09 09:49
文章分类

全部博文(554)

文章存档

2012年(1)

2011年(1)

2009年(8)

2008年(544)

分类:

2008-04-11 15:44:27


常量
第2 章• 类型、运算符和表达式49
u 或U 编译器选择的类型的unsigned 版本
l 或L long
ul 或UL unsigned long
ll 或LL long long
ull 或ULL unsigned long long
浮点常量始终采用十进制表示,必须包含小数点(12.345) 或指数(123e45),或者同时包含二
者(123.34e-5)。缺省情况下,对浮点常量指定的类型为double。您可以将以下后缀之一应
用于任何浮点常量,以显式指定浮点常量的D类型:
f 或F float
l 或L long double
字符常量表示为单个字符或使用一对单引号(’a’) 引起来的转义序列。对字符常量指定的类
型为int,字符常量等效于值由ASCII 字符集中该字符的值确定的整型常数。有关字符及其
值的列表,可以参阅ascii(5)。也可以在字符常量中使用下表所示的任何特殊转义序列。
D支持的转义序列与ANSI-C 中相同。
表2–5D字符转义序列
\a 警报\\ 反斜杠
\b backspace 键\? 问号
\f 换页\’ 单引号
\n 新行\” 双引号
\r 回车\0oo 八进制值0oo
\t 水平制表符\xhh 十六进制值0xhh
\v 垂直制表符\0 空字符
可以在单引号中包括多个字符说明符,以创建根据相应的字符说明符初始化各个字节的整
数。将从左向右读取字符常量中的字节,并按与操作环境的本机字节存储顺序对应的顺序
将各个字节分配到产生的整数。单个字符常量中最多可以包括八个字符说明符。
任何长度的字符串常量都可以通过引在一对双引号中("hello") 来构成。字符串常量可能不
含字面值换行符。要创建包含换行符的字符串,请使用\n 转义序列来代替字面换行符。字
符串常量可以包含上面所示字符常量的任何特殊字符转义序列。与ANSI-C 类似,字符串表
示为由空字符(\0) 结尾的字符数组,该空字符隐式添加到所声明的每个字符串常量中。对
字符串常量指定了特殊的D类型string。D编译器提供了一组特殊功能,用于比较和跟踪
被声明为字符串的字符数组,如第6 章中所述。
常量
50 Solaris 动态跟踪指南• 2006 年7 月
算术运算符
D提供了下表中所示的二元算术运算符,以供在程序中使用。对于整数,这些运算符含义
与在ANSI-C 中的完全一样。
表2–6D二元算术运算符
+ 整数相加
- 整数相减
* 整数相乘
/ 整数相除
% 整数取模
D中只可以对整数操作数或指针(如第5 章中所讨论)执行运算。D程序中不可以对浮点
操作数执行运算。DTrace 执行环境不对整数溢出或下溢采取任何操作。在可能出现溢出和
下溢的情况下,您必须自己检查这些情况。
DTrace 执行环境不会自动检查和报告由于不正确使用/ 和% 运算符而导致的被零除错误。如
果D程序执行无效的相除操作,则DTrace 将自动禁用受影响的检测过程并报告错误。
DTrace 检测到的错误不会对其他DTrace 用户或操作系统内核产生影响,因此,不必担心如
果D程序中包含其中某个未注意到的错误会导致任何破坏。
除了这些二元运算符,+ 和- 运算符也可用作一元运算符;这些运算符比任何二元算术运算
符具有更高的优先级。表2–11 中说明了所有D运算符的优先级顺序和关联属性。可以通过
使用括号( ) 对表达式分组来控制优先级。
关系运算符
D提供了下表中所示的二元关系运算符供在程序中使用。这些运算符都与在ANSI-C 中具有
相同的含义。
表2–7D关系运算符
< 左边的操作数小于右边的操作数
<= 左边的操作数小于或等于右边的操作数
> 左边的操作数大于右边的操作数
>= 左边的操作数大于或等于右边的操作数
== 左边的操作数等于右边的操作数
关系运算符
第2 章• 类型、运算符和表达式51
表2–7D关系运算符(续)
!= 左边的操作数不等于右边的操作数
关系运算符通常用于编写D谓词。每个运算符的计算结果都为int 类型的值,如果条件为
true,则该值等于1,如果条件为false,则该值等于0。
关系运算符可以应用于整数、指针或字符串对。如果比较指针,则结果等于解释为无符号
整数的两个指针的整数比较。如果比较字符串,则结果是通过对两个操作数执行
strcmp(3C) 来确定。以下是一些D字符串比较及其结果的示例:
"coffee" < "espresso" ... 返回1 (true)
"coffee" == "coffee" ... 返回1 (true)
"coffee" >= "mocha" ... 返回0 (false)
也可使用关系运算符比较与枚举类型关联的数据对象和由枚举定义的任何枚举器标记。枚
举是用于创建命名的整型常数的工具,第8 章中对其进行了详细介绍。
逻辑运算符
D提供了以下二元逻辑运算符供在程序中使用。前两个运算符等效于相应的ANSI-C 运算
符。
表2–8D逻辑运算符
&& 逻辑AND:两个操作数都为true 时,结果为true
|| 逻辑OR:一个或两个操作数为true 时,结果为true
^^ 逻辑XOR:只有一个操作数为true 时,结果为true
逻辑运算符通常用于编写D谓词。逻辑运算符AND 使用简化求值法:如果左边的操作数为
false,则不会计算右边的表达式。逻辑运算符OR 也使用简化求值法:如果左边的操作数为
true,则不会计算右边的表达式。逻辑XOR 运算符不使用简化求值法:始终会计算两个表
达式操作数。
除了二元逻辑运算符,一元! 运算符也可用于对单个操作数执行逻辑否定。它将零操作数
转换为一,将非零操作数转换为零。根据约定,D程序员在处理要用于表示布尔值的整数
时使用!,而在处理非布尔整数时使用== 0,尽管两种表达式在含义上相同。
逻辑运算符可以应用于整数或指针类型的操作数。逻辑运算符将指针操作数解释为无符号
整数值。与D中的所有逻辑和关系运算符一样,如果操作数具有非零整数值,则将解释为
true,如果具有零整数值,则将解释为false。
逻辑运算符
52 Solaris 动态跟踪指南• 2006 年7 月
按位运算符
D提供了以下二元运算符用于处理整数操作数中的各个位。这些运算符都与在ANSI-C 中具
有相同的含义。
表2–9D按位运算符
& 按位AND
| 按位OR
^ 按位XOR
<< 将左边的操作数向左移动右边的操作数指定的位数
>> 将左边的操作数向右移动右边的操作数指定的位数
二元& 运算符用于从整数操作数中清除位。二元| 运算符用于在整数操作数中设置位。二
元^ 运算符在只设置了相应操作数位之一的每个位的位置返回1。
移位运算符用于在指定的整数操作数中向左或向右移位。向左移位将使用零填充结果右边
空位的位置。使用无符号整数操作数向右移位将使用零填充结果左边空位的位置。使用带
符号的整数操作数向右移位将使用符号位的值填充左边空位的位置,也称为算术移位操
作。
用负位数将整数值移位,或者移位的位数大于左边操作数本身的位数,将产生未定义的结
果。如果在编译D程序时,编译器可以检测到此条件,则D编译器将产生错误消息。
除了二元逻辑运算符,一元~ 运算符也可用于对单个操作数执行按位否定。它将操作数中
的每个“零”位转换为“一”位,并将操作数中的每个“一”位转换为“零”位。
赋值运算符
D提供了以下二元赋值运算符用于修改D变量。您只可以修改D变量和数组。不可以使用
D赋值运算符修改内核数据对象和常量。赋值运算符与在ANSI-C 中具有相同的含义。
表2–10D赋值运算符
= 将左边的操作数设置为等于右边的表达式值
+= 将左边的操作数递增右边的表达式值
-= 将左边的操作数递减右边的表达式值
*= 将左边的操作数与右边的表达式值相乘
/= 将左边的操作数与右边的表达式值相除
赋值运算符
第2 章• 类型、运算符和表达式53
表2–10D赋值运算符(续)
%= 将左边的操作数按右边的表达式值取模
|= 将左边的操作数与右边的表达式值进行按位OR 运算
&= 将左边的操作数与右边的表达式值进行按位AND 运算
^= 将左边的操作数与右边的表达式值进行按位XOR 运算
<<= 将左边的操作数向左移动右边的表达式值指定的位数
>>= 将左边的操作数向右移动右边的表达式值指定的位数
除了赋值运算符= 以外,所提供的其他赋值运算符是将= 运算符与先前说明的某个其他运算
符配合使用的简写形式。例如,表达式x = x + 1 等效于表达式x += 1,不同的是表达式x
计算一次。这些赋值运算符遵守与前面说明的二元格式相同的操作类型规则。
任何赋值运算符的结果都是等于左边表达式的新值的表达式。您可以将赋值运算符或到现
在为止说明的任何运算符与任意复杂度的格式表达式配合使用。也可以使用括号( ) 来对
复杂表达式中的条件分组。
递增和递减运算符
D提供了特殊的一元++ 和-- 运算符用于递增和递减指针和整数。这些运算符的含义与在
ANSI-C 中相同。这些运算符仅可应用于变量,可以在变量名称之前或之后应用。如果运算
符显示在变量名称之前,则将首先修改变量,于是产生的表达式等于变量的新值。例如,
以下两个表达式产生相同的结果:
x += 1; y = ++x;
y = x;
如果运算符显示在变量名称之后,则在返回变量的当前值以供在表达式中使用之后,将修
改该变量。例如,以下两个表达式产生相同的结果:
y = x; y = x--;
x -= 1;
您可以使用递增和递减运算符来创建新的变量,同时可以不声明这些变量。如果省略变量
声明,并将递增或递减运算符应用于变量,则该变量将隐式声明为int64_t 类型。
递增和递减运算符可以应用于整数或指针变量。应用于整数变量时,运算符将对相应的值
递增或递减一。应用于指针变量时,运算符将对指针地址递增或递减指针所引用的数据类
型的大小。D中的指针和指针运算将在第5 章中讨论。
递增和递减运算符
54 Solaris 动态跟踪指南• 2006 年7 月
条件表达式
尽管D不支持if-then-else 结构,但它支持使用? 和: 运算符的简单条件表达式。这些运算
符可以关联三元表达式(其中,第一个表达式用于根据条件计算另两个表达式中的一
个)。例如,以下D语句可用于根据i 的值将变量x 设置为两个字符串之一。
x = i == 0 ? "zero" : "non-zero";
在此示例中,将首先计算表达式i == 0 以确定该表达式为true 还是false。如果第一个表达
式为true,则将计算第二个表达式,并且?: 表达式将返回其值。如果第一个表达式为
false,则将计算第三个表达式,并且?: 表达式将返回其值。
与任何D运算符一样,可以在单个表达式中使用多个?: 运算符来创建更复杂的表达式。例
如,以下表达式将采用一个char 变量c,该变量包含0-9、a-z 或A-Z 范围中的一个字符,
然后在将此字符解释为十六进制(以16 为基数)整数格式的数字时返回此字符的值。
hexval = (c >= ’0’ && c <= ’9’) ? c - ’0’ :
(c >= ’a’ && c <= ’z’) ? c + 10 - ’a’ : c + 10 - ’A’;
与?: 配合使用的第一个表达式必须为指针或整数,以便计算表达式的实际值。第二个和第
三个表达式可以为任何兼容类型。在一个路径返回字符串,另一个路径返回整数的情况
下,不可以构造条件表达式。第二个和第三个表达式也不可以调用跟踪函数(如trace() 或
printf())。如果要根据条件跟踪数据,请改为使用第1 章中讨论的谓词。
类型转换
使用不同但兼容的类型构造表达式时,将会执行类型转换以便确定所产生表达式的类型。
类型转换的D规则与ANSI-C 中整数的算术转换规则相同。这些规则有时又称为常用算术转
换。
以下是说明转换规则的简单方法:每个整数类型按char、short、int、long、long long 顺
序排列,相应的无符号类型分配的级别高于其带符号类型,但低于下一个整数类型。使用
两个整数操作数(如x + y)构造表达式,且操作数为不同的整数类型时,具有最高级别的
操作数类型将用作结果类型。
如果需要转换,则首先将低级别的操作数提升为高级别的类型。提升不会实际更改操作数
的值:它仅根据符号将值扩展为更大的容器。如果提升无符号的操作数,则所产生整数的
未用高序位将使用零填充。如果提升带符号操作数,则将通过执行符号扩展填充未用的高
序位。如果将带符号类型转换为无符号类型,则将首先对带符号类型进行符号扩展,然后
分配由转换确定的新的无符号类型。
也可以将整数和其他类型从一种类型显式地强制转换为另一种类型。在D中,可以将指针
和整数强制转换为任何整数或指针类型,但不能转换为其他类型。强制转换和提升字符串
和字符数组的规则将在第6 章中讨论。整数和指针强制转换使用表达式构成,如下所示:
y = (int)x;
类型转换
第2 章• 类型、运算符和表达式55
其中,目标类型括在括号中,置于源表达式的前面。可以通过执行提升将整数强制转换为
高级别的类型。可以通过将整数多余的高顺序位填充零来强制将整数转换为低级别的类
型。
因为D不允许浮点运算,所以不允许执行浮点操作数转换或强制转换,也没有定义隐式浮
点转换的规则。
优先级
下表说明了运算符优先级和关联性的D规则。这些规则有点复杂,但为了保持与ANSI-C
运算符优先级规则的完全兼容性,这是必需的。表中项的顺序为从最高优先级到最低优先
级。
表2–11D运算符优先级和关联性
运算符关联性
() [] -> . 从左到右
! ~ ++ -- + - * & (type) sizeof stringof offsetof xlate 从右到左
* / % 从左到右
+ - 从左到右
<< >> 从左到右
< <= > >= 从左到右
== != 从左到右
& 从左到右
^ 从左到右
| 从左到右
&& 从左到右
^^ 从左到右
|| 从左到右
?: 从右到左
= += -= *= /= %= &= ^= |= <<= >>= 从右到左
, 从左到右
表中还有多个运算符我们尚未讨论;后续章节中将对它们进行讨论:
优先级
56 Solaris 动态跟踪指南• 2006 年7 月
sizeof 计算对象的大小(第7 章)
offsetof 计算类型成员的偏移(第7 章)
stringof 将相应操作数转换为字符串(第6 章)
xlate 转换数据类型(第40 章)
一元& 计算对象的地址(第5 章)
一元* 取消引用指向对象的指针(第5 章)
-> 和. 访问结构类型或联合类型的成员(第7 章)
表中列出的逗号(,) 运算符用于与ANSI-C 逗号运算符兼容,可以使用该运算符按照从左到
右的顺序计算一组表达式的值,然后返回最右边表达式的值。提供此运算符是为了与C 严
格兼容,通常不应使用。
运算符优先级表中的() 项表示函数调用;第1 章中说明了函数调用(如printf() 和
trace())的示例。D中也使用逗号列出函数的参数以及用于构成关联数组键的列表。此逗
号与逗号运算符不同,它不一定从左向右计算。D编译器不提供对函数参数或关联数组键
的计算顺序的保证。在这些上下文中使用会产生负面影响的表达式(如表达式i 和i++
对)时务必小心。
运算符优先级表中的[] 项表示数组或关联数组引用。第1 章说明了关联数组的示例。
第9 章中介绍了称为聚合的特殊类型关联数组。[] 运算符同样可用于对大小固定的C 数组
建立索引,如第5 章中所述。
优先级
第2 章• 类型、运算符和表达式57
58
变量
D提供了两种基本类型的变量供在跟踪程序中使用:标量变量和关联数组。在第一章的示
例中简单介绍了这些变量的用法。本章将详细介绍D变量的规则以及如何将变量与不同的
作用域关联。在第9 章中将讨论称为聚合的特殊类型的数组变量。
标量变量
标量变量用于表示一个大小固定的数据对象(如整数和指针)。标量变量也可用于表示由
一个或多个原始类型或复合类型组成的大小固定的对象。D提供了用于创建对象数组和复
合结构的功能。DTrace 还通过允许字符串扩大到预定义的最大长度,将字符串表示为大小
固定的标量。第6 章中将进一步讨论如何在D程序中控制字符串的长度。
在D程序中首次对先前未定义的标识符赋值时,会自动创建标量变量。例如,要创建一个
名为x 的int 类型的标量变量,只需在任何探测子句中为该变量指定一个int 类型的值:
BEGIN
{
x = 123;
}
按照此方式创建的标量变量为全局变量:其名称和数据存储位置只需定义一次,并且在D
程序的所有子句中都可见。每次引用标识符x 时,就是在引用与此变量关联的单个存储位
置。
与ANSI-C 不同,D编程语言不需要显式声明变量。如果确实要声明一个全局变量,以在使
用该变量之前为其显式指定名称和类型,则可以在程序中探测子句外部进行声明,如下例
所示。在大多数D程序中无需显式声明变量,但如果要谨慎控制变量类型,或要在程序的
开头使用一组声明和注释来说明该程序的变量及其含意,显式声明变量会很有用。
3第3 章
59
int x; /* declare an integer x for later use */
BEGIN
{
x = 123;
...
}
与ANSI-C 声明不同,D变量声明不能指定初始值。必须使用BEGIN 探测子句指定所有初始
值。在首次引用变量之前,DTrace 将使用零填充所有全局变量存储空间。
D语言定义对D变量的大小和数量不设限制,但是DTrace 实现和系统中可用内存会定义一
些限制。D编译器在编译程序时将强制执行可应用的任何限制。在第16 章中可了解有关如
何调整与程序限制相关的选项的更多信息。
关联数组
关联数组用于表示数据元素的集合,可通过指定一个称为键的名称来检索这些数据元素。
D关联数组的键由称为元组的标量表达式值的列表构成。您可以将数组元组本身视为函数
的假想参数列表,在引用该数组时系统将调用该函数来检索相应的数组值。每个D关联数
组都有一个固定的键签名,该签名由固定数量的元组元素组成,其中每个元素具有给定的
固定类型。可以在D程序为每个数组定义不同的键签名。
关联数组与大小固定的常规数组不同,因为关联数组对元素的数量没有预定义的限制。关
联数组的元素可以通过任何元组建立索引,而不是仅使用整数作为键,这些元素并不存储
在预先分配的连续存储位置中。在C、C++ 或JavaTM 语言程序中要使用散列表或其他简单
字典数据结构的情况下,使用关联数组会很有用。使用关联数组可以为D程序中捕获的事
件和状态创建动态历史记录,使用该历史记录可创建更复杂的控制流。
要定义关联数组,请编写以下形式的赋值表达式:
name [ key ] = expression ;
其中,name 是任何有效的D标识符,key 是逗号分隔的一个或多个表达式的列表。例如,
以下语句使用键签名[ int, string ] 定义关联数组a,并将整数值456 存储在由元组[ 123,
"hello" ] 命名的位置中:
a[123, "hello"] = 456;
关联数组
60 Solaris 动态跟踪指南• 2006 年7 月
对于给定数组中的所有元素,数组中包含的每个对象的类型也是固定的。由于已对a 指定
了整数456,所以该数组中存储的每个后续值也将为int 类型。可以使用第2 章中定义的任
何赋值运算符,根据为每个运算符定义的操作数规则来修改关联数组元素。如果尝试进行
不兼容的赋值,D编译器将产生相应的错误消息。您可以将对标量变量使用的任何类型用
于关联数组键或值。但不能将关联数组作为键或值嵌套在另一个关联数组中。
您可以使用与数组键签名兼容的任何元组引用关联数组。元组兼容性规则与函数调用和变
量赋值的规则相似:元组的长度必须相同,且实际参数列表中的每种类型必须与正式键签
名中的相应类型兼容。例如,如果按照如下所示定义关联数组x:
x[123ull] = 0;
则键签名为unsigned long long 类型,值为int 类型。也可使用表达式x[’a’] 引用该数
组,因为根据第55 页中的“类型转换”中说明的算术转换规则,由int 类型的字符常量
’a’ 组成的元组和长度1 与键签名unsigned long long 兼容。
如果需要在使用D关联数组前对其进行显式声明,可以在程序源代码中探测子句外部创建
数组名称和键签名的声明。
int x[unsigned long long, char];
BEGIN
{
x[123ull, ’a’] = 456;
}
定义关联数组后,将允许引用兼容键签名的任何元组,即使先前未对要引用的元组赋值。
访问未赋值的关联数组元素定义为返回使用零填充的对象。此定义的后果是,在对关联数
组元素赋非零值之前,将不会为该元素分配基础存储空间。相反,对关联数组元素赋值零
将会导致DTrace 解除分配基础存储空间。此行为很重要,因为可对关联数组元素分配的外
部动态变量空间是有限的。如果在尝试分配时该空间已用完,分配将会失败,并生成一条
错误消息,指示将进行动态变量删除。不再使用的关联数组元素将赋值零。有关消除动态
变量删除的其他方法,请参见第16 章。
 
 
以上文章转自于 : http://developers.sun.com.cn/
阅读(492) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~