Ada 编程/变量
变量是引用,代表存储在特定内存地址的值。
变量被认为具有值,并且可能具有 数据类型。如果变量具有类型,则只能将此类型的值分配给它。变量并不总是具有类型。
一个值可以具有多种不同类型的多个值:整数 (7)、比率 (1/2)、(近似)实数 (10.234)、复数 (4+2i)、字符 ('a')、字符串 ("hello"),等等。
不同的语言使用不同的名称来表示它们的类型,并且可能不包含上述任何一种。
赋值语句
[编辑源代码]赋值语句用于将变量设置为新值。
赋值语句写为 名称 := 值
。
X := 10;
示例将变量X设置为整数10。赋值语句覆盖变量的内容,并且之前的值将丢失。
在某些语言中,在使用变量之前,需要先声明它,声明指定类型。
Ada 也是如此。声明如下
declare
X : Integer := 10;begin
Do_Something (X);end
;
用途
[编辑源代码]变量存储程序中的所有内容。任何有用程序的目的都是修改变量。
如果没有变量,我们就无法创建超出经典“Hello World!”示例的程序。Ada 中的变量必须声明。它们不能在未声明的情况下就神奇地出现在程序中。变量声明看起来像这样
Variable_Name : Variable_Type [:=Optional Value]
如果在声明时为变量分配了一个值,则称该变量已初始化。可以通过逗号分隔变量名称,在一次声明中声明多个相同类型
的变量
Variable_A, Variable_B : Variable_Type [:=Optional Value]
如您所见,将值分配给变量是可选的。编译器只需要知道您打算让变量保存哪种数据(类型
)。它不关心变量中是否有实际数据。当您声明一个变量时,您实际上是在要求分配特定数量的内存。当然,实际的内存量取决于声明的类型
。一个Integer
可能占用 4 个字节的内存,而一个String (1 .. 10)
可能占用 10 个字节的内存。变量名称只不过是一个符号名称,与分配给该变量的内存中的任何值相关联。
如果我们在声明期间为变量分配一个值,它将看起来像这样
Variable_Name : Variable_Type := Variable_Value
让我们尝试一些真实的 Ada 变量。如上所述,Ada 中的变量必须声明为指向特定类型
的数据
A_String_Variable : String (1 .. 10);
这里我们将变量A_String_Variable
声明为String
类型,其长度为 10 个字符,(1 .. 10)
。让我们看看如果我们在声明期间为A_String_Variable
分配一个值会是什么样子
A_String_Variable : String (1 .. 10) := "abcdefghij";
这里我们首先声明了A_String_Variable
变量,然后对其进行了初始化。
在String
类型的情况下,可以省略长度,我们可以简单地写
A_String_Variable : String := "abcdefghij";
这里,"abcdefghij"
的分配隐式地声明A_String_Variable
的长度为(1 .. 10)
,因为这是分配字符串的长度。
变量可以声明为任何类型
,无论是String
、Integer
、records
、array
还是自定义类型。让我们尝试声明各种变量
An_Array : array (1 .. 3) of Integer := (1, 2, 3);
A_Positive : Positive := 10;
type Colors is (Red, Blue, Green);
Color : Colors := Red;
type Person is record
Name : String (1 .. 12);
Age : Natural;
end record;
A_Person : Person;
B_Person : Person := (Name => "Thomas Løcke", Age => 37);
注意自定义Colors
类型。首先我们声明新类型,然后声明该类型的Color
变量。这是 Ada 最大的优势之一:能够声明自己的类型和子类型。可以在 类型系统 文章中找到更多相关信息。
现在,让我们尝试在实际程序中使用上面声明的变量
with Ada.Text_IO;
procedure VarCon is
package IO renames Ada.Text_IO;
A_String : String (1 .. 8) := "A_String";
B_String : String := "B_String";
An_Array : array (1 .. 3) of Integer := (1, 2, 3);
A_Integer : Integer := 10;
type Colors is (Red, Blue, Green);
package IOENUM is new Ada.Text_IO.Enumeration_IO (Colors);
Color : Colors := Red;
type Person is record
Name : String (1 .. 12);
Age : Natural;
end record;
A_Person : Person;
begin
IO.Put_Line (Item => A_String);
IO.Put_Line (Item => B_String);
A_String := "String_A";
B_String := "String_B";
IO.Put_Line (Item => A_String);
IO.Put_Line (Item => B_String);
for i in An_Array'Range loop
IO.Put (Item => i'Img & ":" & An_Array (i)'Img);
IO.New_Line;
end loop;
An_Array := (1 => 10, 2 => 20, 3 => 30);
for i in An_Array'Range loop
IO.Put (Item => i'Img & ":" & An_Array (i)'Img);
IO.New_Line;
end loop;
IO.Put_Line (Item => A_Integer'Img);
IOENUM.Put (Item => Color);
IO.New_Line;
A_Person := (Name => "Thomas Løcke",
Age => 37);
IO.Put_Line (Item => A_Person.Name);
end VarCon;
执行后,上述程序应输出以下内容
A_String B_String String_A String_B 1: 1 2: 2 3: 3 1: 10 2: 20 3: 30 10 RED Thomas Løcke
在这里我们实际上可以看到为什么变量被称为变量:它们的值是可变的。
请注意,我们如何能够更改包含在例如A_String
变量中的数据。当我们声明它时,我们分配了A_String
的值(该变量被认为是已初始化的),但稍后我们为A_String
分配了另一个值:String_A
。这正是每个初学者程序员都必须理解的变量的核心概念:变量是可变的。变量名称只是一个指向内存位置的引用,该位置存储特定类型
的数据。确切的数据可能会在程序运行期间发生很多变化,但变量名称和类型
保持不变。
如果变量在程序执行期间不发生变化,那么我们有一个更好的选择:常量。它们是变量的坚强兄弟。
最后,让我们简要看一下变量范围与块的关系。它们在何时何地可见?这可以通过一个简单的程序来更好地理解
with Ada.Text_IO;
procedure Scope is
package IO renames Ada.Text_IO;
Name : String := "Thomas Løcke";
begin
IO.Put_Line (Item => "1:" & Name);
declare
Name : String := "Dwight S. Miller";
begin
IO.Put_Line (Item => "2:" & Name);
end;
IO.Put_Line (Item => "3:" & Name);
declare
begin
IO.Put_Line (Item => "4:" & Name);
end;
end Scope;
我们从上面得到的输出如下所示
1:Thomas Løcke 2:Dwight S. Miller 3:Thomas Løcke 4:Thomas Løcke
请注意,Name
在第一个块中声明为局部变量。第一个块中的声明绝不会干扰“全局”Name
变量。如果未为块声明Name
变量,则将使用“全局”Name
变量,如最后一个块中所示,其中打印了Thomas Løcke
,即使该块中没有进行过此类分配。
因此,关于块的变量范围非常简单明了:块从其父块继承变量,然后可以通过重新声明变量在块中局部覆盖这些变量。