跳转到内容

Futurebasic/语言/数据类型

来自维基教科书,开放书籍,构建开放世界

数据类型和数据表示

[编辑 | 编辑源代码]

修订:2000年5月30日(版本3)

整数可以表示为字面量,符号常量或变量。

整数字面量

[编辑 | 编辑源代码]
  • 十进制: 一串十进制数字,可选地以 "+" 或 "-" 开头。
    例子
     7244      -328442
  • 十六进制: 一串最多 8 位十六进制数字,以 "&" 或 "&H" 或 "0x" (即零-x) 开头。十六进制数字包括数字 0 到 9,以及字母 AF。字母可以是大写或小写。
    例子
     &H12a7      0x47BeeF      &42AD9
    
  • 八进制: 一串最多 10 位八进制数字,以 "&O" (即字母 "O",而不是零) 开头。八进制数字包括数字 0 到 7。
    例子
     &o70651      &o32277
    
  • 二进制: 一串最多 32 位二进制数字,以 "&x" 开头。二进制数字包括数字 0 和 1。
    例子
     &x0100011      &x10110000111011001
    
  • 引号: 一串最多 4 个字符,用双引号括起来,并在初始引号之前有一个下划线。引号字符串中的每个字符根据字符的 ASCII 码在生成整数的内部位模式中表示 8 位。
    例子
     _"TEXT"      _"N*"
    

注意:十六进制、八进制、二进制和引号字面量反映了整数在内存中存储的实际位模式。这些可以解释为正数或负数,具体取决于它们被分配给哪种类型的变量。如果它们没有被分配给任何变量,它们通常被解释为正数。

符号常量

[编辑 | 编辑源代码]

符号常量是一个由下划线字符开头的标识符。FB 中有许多符号常量具有预定义的值。您也可以在程序中定义自己的符号常量,可以使用 BEGIN ENUM...END ENUM 块;或 DIM RECORD...END RECORD 块;或使用 "常量声明" 语句。常量声明语句具有以下语法

_constantName = staticExpression

其中 _constantName 是一个以前未定义的符号常量,staticExpression 是一个 "静态整型表达式" (参见 附录 D: 数字表达式)。staticExpression 的值必须在 -2,147,483,648 到 +2,147,483,647 之间。符号常量一旦被分配了一个值,该值在程序中就不能被更改。与所有常量一样,符号常量具有全局作用域。

常量声明还可以包含使用以下格式之一的 Pascal 风格字符串

_constantName$    = "I am a string constant" 
_constantTab$     = 9      : REM CHR$(9) = tab character 
_constantCR$      = 13     : REM CHR$(13) = carriage return 
_twoByteKanjiChar = 10231  : REM KCHR$(10231)

整型变量

[编辑 | 编辑源代码]

FB 中有六种不同的整型变量;它们在所占存储空间和可以表示的值范围方面有所不同。整型变量的名称可能以类型标识后缀结尾,该后缀指示其类型;或者,您可以使用 DIM 语句中的 AS 子句声明整型变量的类型。如果变量没有类型标识后缀,并且没有使用 AS 子句声明,则 FB 会检查是否有任何 DEF<type> 语句适用于该变量。最后,如果变量不能通过以上任何方式进行类型化,则 FB 会将类型 "带符号短整型" 分配给该变量。整型数组和整型记录字段通过类似的方式进行类型化。

类型 存储 范围 类型识别
无符号字节 1 字节 0..255
x``
DIM x AS Unsigned Byte
DIM x AS Unsigned Char
带符号短整型 2 字节 -32768..+32767
x%
DIM x AS Int
DIM x AS Word
DIM x AS Short
无符号短整型 2 字节 0..65535
x%`
DIM x AS Unsigned Int
DIM x AS Unsigned Word
DIM x AS Unsigned Short
带符号长整型 4 字节 -2147483648..+2147483647
x&
DIM x AS Long
无符号长整型 4 字节 0..4294967295
x&`
DIM x AS Unsigned Long

"实数" 是可能具有小数部分的数字。它们可以表示为字面量或变量。

实数字面量

[编辑 | 编辑源代码]
  • 标准记数法: 一串十进制数字,包括一个小数点;可选地以 "+" 或 "-" 开头。
    例子
     17.3      -62.       0.03
    
  • 科学记数法: 一串字符,格式如下:mantissa{E|e}exponent
    mantissa 是一串十进制数字,可能包含一个小数点,可选地以 "+" 或 "-" 开头;exponent 是一串十进制数字,可选地以 "+" 或 "-" 开头。例子:
     3e-20      -6.7E4      0.05E+14
    

    用科学记数法表示的数字的值为:mantissa 10exponent

实型变量

[编辑 | 编辑源代码]

FB 中有三种类型的实型变量;它们在所占存储空间、可以表示的值范围及其精度 (有效数字位数) 方面有所不同。

定点实数
[编辑 | 编辑源代码]

定点实型变量必须在 DIM 语句中声明,使用 AS FIXED 子句。它的精度约为小数点后 5 位,可以处理大约 -32767.99998 到 +32767.99998 之间的数字。定点变量占用 4 字节的存储空间。

浮点实数
[编辑 | 编辑源代码]

FB 支持两种浮点实型变量。浮点变量的名称可能以类型标识后缀结尾,该后缀指示其类型;或者,您可以使用 dim 语句中的 as 子句声明浮点变量的类型。如果变量没有类型标识后缀,并且没有使用 as 子句声明,则 FB 会检查是否有任何 defsng <letterRange>defdbl <letterRange> 语句适用于该变量。浮点数组和浮点记录字段通过类似的方式进行类型化。

您可以修改 FB 在处理这些变量之一时使用的方法。一组常量保存在 headers 文件夹中的一个文件中。(路径:FB Extensions/Compiler/Headers/UserFloatPrefs)。如果您想更改所有项目的这些参数,请将名为“UserFloatPrefs”的文件复制到User Libraries文件夹。User Libraries文件夹位于与编辑器相同的级别。

//
// Required Floating Point Constants //
//
_NumberLeadingSpace = _True //FB II Default = _true <br>
_RoundUpFloat2Long = _true // Un-remark to round up Float to Integer

双精度浮点数变量占用更多存储空间,代表更大的值范围,并且比单精度浮点数变量具有更高的精度。

类型类型标识

单精度

x! (4 字节)
dim as single x

双精度

x# (8 字节
dim as double x

字符串

[edit | edit source]

字符串是最多 255 个字符的列表,通常被解释为 MacPascal 编码中的文本。字符串可以表示为文字或变量。

字符串文字

[edit | edit source]

字符串文字是由一对双引号包围的一组字符(注意:在某些上下文中,例如在data语句中,引号是可选的)。如果字符串文字包含一对连续的双引号,则它们被解释为一个(单个)嵌入的双引号,并被视为字符串的一部分,而不是分隔符。示例

print "I said, ""Hello."""

输出

I said, "Hello."

字符串变量

[edit | edit source]

dim语句以以下方式指定字符串变量及其大小

dim as Str255 s  // s is a 255 character string
dim as Str63  s  // s is a 63 character string
dim as Str31 s  // s is a 31 character string
dim as Str15 s  // s is a 15 character string

dim s as Str255  // s is a 255 character string
dim s$           // s is a 255 character string
dim 3 s$         // s is a 3 character string [the custom size value can range from 1 to 255]

dim as Str31 s$  // s is a 255 character string [this anomaly, present in the old FB Compiler, may be removed from FBtoC]

如果变量没有类型标识后缀,并且没有用as子句声明,那么 FB 会检查是否有任何适用于该变量的defstr <letterRange>语句。

字符串数组和字符串记录字段的类型与字符串变量类似。

在内部,字符串以 Pascal 格式存储,以一个长度字节开头,该字节指示当前字符串中的字符数(0 到 255)。长度字节紧随其后的是字符串的字符,每个字符一个字节。FutureBASIC 始终为内存中的字符串变量分配偶数个字节;这足以包含长度字节,加上变量的最大字符串长度的足够字符字节,再加上一个额外的“填充”字节(如果需要)以使总量达到偶数。使用sizeof()来确定分配给特定字符串变量的字节数。

容器

[edit | edit source]

容器是编译器管理的句柄,可以保存高达 2 GB 的 ASCII 或数字信息。容器可以用双美元符号(dim myContainer$$)或在dim as语句中(dim as container myContainer)标识。在 FBtoC 中,容器仅保存 ASCII 信息,不允许数字赋值和操作。

容器始终是全局的。尝试在局部函数内定义容器将在编译期间导致错误消息。当容器首次被定义时,它是一个值为零的长整型变量。一旦数据被放入容器中,就会分配一个句柄,并将数据移动到该句柄。要释放分配的句柄,请使用myContainer$$ = ""将容器设置为空字符串。

由于容器可以保存 ASCII 或数字信息,因此存在一些权衡取舍。首先是速度。存储在容器中的数值首先被转换为 ASCII。当需要数学运算时,数据在计算之前会重新转换。(在 FBtoC 中,容器仅保存 ASCII 信息,不允许数字赋值和操作。)

另一个限制与容器的填充方式有关。由于 FB 不知道容器中可能包含什么数据,因此它必须评估等号另一侧的信息以查看应该做什么。如果该数据是一系列 Pascal 字符串,那么容器必须限制为 255 个字符。

myContainer$$ = a$ + b$ + c$

如果信息是要连接的字符串,而等号右侧只包含 Pascal 风格的字符串,那么您必须从不同的方向进行操作。

myContainer$$ = a$
myContainer$$+= b$
myContainer$$+= c$

在某些情况下,编译器将无法确定您想到的操作类型。例如...

a$$ = b$$ + c$$

编译器不知道它应该连接字符串还是添加数字。您可以通过插入一个额外的运算符来强制执行正确操作。

a$$ = b$$ + c$$ + 0  : REM math
a$$ = b$$ + c$$ + "" : REM strings

对于减号或乘法(星号)符号等其他数学运算符来说,这不是问题,因为它们与字符串无关。

容器不能以传统意义上的方式进行比较。这是因为比较本质上必须返回一个数值。如果您执行类似PRINT a$ = b$的语句,结果将是零(_false)或 -1(_zTrue)。我们提供了一个替代函数,可以帮助您处理比较。

rslt& = fn FBcompareContainers(a$$,b$$)

如果a$$小于b$$,那么结果将为负数,并且将表示找到差异的字符位置。如果rslt&为 -3000,那么a$$b$$在最初的 2999 个字符中是相同的,此时发现b$$中的下一个字符小于a$$中的字符。

rslt&为零时,容器相等。

rslt&为正数时,它指向确定a$$大于b$$的字符位置。

容器作为可重定位块存储在应用程序堆中。您可以按如下方式提取这些块的句柄

hndl& = [@myContainer$$]

请注意,如果容器已被清除或从未初始化,则句柄可能为零。

与用于填充编辑字段的语法类似的语法可用于将信息传递给容器。百分号 (%) 表示容器将用_"TEXT"资源的内容填充。与号 (&) 表示 FB 将用来自句柄的信息填充容器。

a$$ = %resID //  fill container with TEXT res ID resID
a$$ = & myHandle; // fill container with contents of myHandle

注意
您不能在等号右侧使用包含容器和/或 Pascal 字符串的复杂表达式。不要使用

c$$ = c$$ + left$$(a$$,10)
d$$ = c$$ + a$

使用

c$$ += left$$(a$$,10)
d$$ = c$$
d$$ += a$

指针

[edit | edit source]

指针变量始终在dim语句中声明。它可以使用as pointer(或as ptr)子句,或as ptrType子句来声明,其中ptrType是在先前#define语句中标识为pointer类型的类型。如果as pointer 子句包含to子句,那么该变量被标识为“指向”所指示类型的数据结构;否则它被视为“通用”指针。

指针的值实际上是一个长整型;它是数据结构的地址。在某些情况下,指针的值可能为_nil(零),这表示指针当前没有“指向”任何内容。

如果您将指针变量声明为指向特定记录类型,则可以使用指针变量来引用记录中的特定字段(有关更多信息,请参见附录 B:变量)。这是使用指针变量而不是长整型变量来存储数据结构地址的主要优点。

句柄

[edit | edit source]

句柄变量始终在DIM语句中声明。它可以使用AS HANDLE(或AS HNDL)子句,或AS hdlType子句来声明,其中hdlType是在先前#DEFINE语句中标识为HANDLE类型的类型。如果AS HANDLE子句包含TO子句,那么该变量被标识为指向所指示类型的数据结构的句柄;还有一些预定义类型(RGNHANDLETEHANDLE)被识别为指向特定类型的 MacOS 结构(具体来说:指向区域和 TextEdit 记录)。如果变量仅声明为“AS HANDLE”(没有TO子句),则它被视为“通用”句柄。

句柄的值实际上是一个长整型;它是指向包含数据结构的可重定位块的“主指针”的地址。在某些情况下,句柄的值可能为_nil(零),这表示它当前不引用任何数据结构。您可以使用长整型变量来存储与句柄变量相同的地址,并且在许多情况下,句柄变量和长整型变量是可互换的。

如果您将句柄变量声明为引用特定记录类型,则可以使用句柄变量来引用记录中的特定字段(有关更多信息,请参见附录 B:变量)。这是使用句柄变量而不是长整型变量来存储句柄值的主要优点。

记录

[edit | edit source]

记录是存储在内存中的数据项集合。您可以将整个记录作为一个单元访问,也可以单独访问其数据元素。与所有元素类型相同的数组不同,记录的元素(也称为“字段”)可以是不同类型的。

记录变量必须在dim语句中声明

dim varName as RecordType
dim as RecordType  varName

其中 RecordType 是预定义的记录类型。您可以使用begin record ... end record 块来定义记录类型及其字段。此外,FB 识别两种内置记录类型:RectPoint。您可以使用varName.field 语法访问记录变量的字段(参见 附录 B:变量)。

类型的兼容性

[编辑 | 编辑源代码]

您可以将一种类型的数值分配给另一种类型的变量,有时会有一些限制。下表显示了哪些类型的数值可以分配给哪些类型的变量。

数值
变量
有符号。
字节
无符号。
字节
有符号。
无符号。
有符号。
长整型
无符号。
长整型
定点型 简单型 双精度型 字符串 指针 句柄 记录
有符号。字节 可以 2 2 2 2 2 2,3 2,3 2,3 2,3,8 不可 不可 不可
无符号。字节 1 可以 1,2 2 1,2 2 1,2,3 1,2,3 1,2,3 1,2,3,8 不可 不可 不可
有符号。字 可以 可以 可以 2 2 2 3 2,3 2,3 2,3,8 不可 不可 不可
无符号。字 1 可以 1 不可 1,2 2 1,3 1,2,3 1,2,3 1,2,3,8 不可 不可 不可
有符号。长整型 可以 可以 可以 可以 可以 2 3 2,3 2,3 2,3,8 10 10 不可
无符号。长整型 1 可以 1 可以 1,2 可以 1,3 1,2,3 1,2,3 1,2,3,8 10 10 不可
定点型 可以 可以 可以 2 2 2 可以 2,4 2,4 2,4,8 不可 不可 不可
简单型 可以 可以 可以 可以 4 4 4 可以 4 4,8 不可 不可 不可
双精度型 可以 可以 可以 可以 可以 可以 可以 可以 可以 8 不可 不可 不可
字符串 5,8 5,8 5,8 5,8 5,8 5,8 5,8 5,8 5,8 5 5,8 5,8 不可
指针 可以 可以 可以 可以 可以 可以 2,3 2,3 2,3 2,3,8 6 不可 不可
句柄 可以 可以 可以 可以 可以 可以 2,3 2,3 2,3 2,3,8 可以 7 不可
记录 不可 不可 不可 不可 不可 不可 不可 不可 不可 不可 不可 不可 9
  1. 将负值分配给无符号整型可能会产生意外结果。
  2. 将超出类型范围的数值分配给变量可能会产生意外结果。
  3. 结果将四舍五入到最接近的整数。
  4. 可能会丢失一些精度位。
  5. 确保目标字符串变量声明了足够的存储空间。
  6. 两者必须是指向相同类型(或两者都是“通用”指针)的指针。
  7. 两者必须是指向相同类型(或两者都是“通用”句柄)的句柄。
  8. 自动字符串/数字转换需要特殊的首选项设置;否则,使用VAL[&]STR$ 函数。
  9. 两者必须是相同的记录类型(如果是“真实”记录)或具有相同的长度(如果是“伪”记录)。
  10. 句柄或指针引用的事物类型的相关信息在句柄或指针值被分配给长整型变量时会丢失。(这在某些情况下可能有用,如果您想“强制”指针指向不同的类型。)
华夏公益教科书