有符号的
echo sizeof(int) # 取决于系统和编译器,一般是4
echo sizeof(int8) # size = 1
echo sizeof(int16) # size = 2
echo sizeof(int32) # size = 4
echo sizeof(int64) # size = 8
proc foo1(x: int64) =
echo x
# 接受任意有符号整数,同等于"int|int8|int16|int32|int64",比直接指定int64更语义化
proc foo2(x: SomeSignedInt) =
echo x
foo1(888i64)
foo2(888i64)
无符号的
echo sizeof(uint) # 取决于系统和编译器,一般是4
echo sizeof(uint8) # size = 1
echo sizeof(uint16) # size = 2
echo sizeof(uint32) # size = 4
echo sizeof(uint64) # size = 8
proc foo1(x: uint64) =
echo x
# 接受任意无符号整数,同等于"uint|uint8|uint16|uint32|uint64",比直接指定uint64更语义化
proc foo2(x: SomeUnsignedInt) =
echo x
foo1(888u64)
foo2(888u64)
如果打算接受有符号和无符号的,可以用SomeInteger
# 接受任意整数类型,同等于"SomeSignedInt|SomeUnsignedInt"
proc foo(x: SomeInteger) =
echo x
foo(888i64)
foo(888u64)
echo sizeof(float) # 取决于系统和编译器,一般是8
echo sizeof(float32) # size = 4
echo sizeof(float64) # size = 8
# 接受任意浮点类型,同等于"float|float32|float64"
proc foo(x: SomeReal) =
echo x
foo(3.14f)
foo(3.14f32)
foo(3.14f64)
foo(2e2)
如果可以接受任何数字类型,可以用SomeNumber
# 接受任意数字类型,同等于"SomeInteger|SomeReal"
proc foo(x: SomeNumber) =
echo x
foo(666)
foo(3.14f)
foo(888u64)
var b: bool
echo sizeof(b) # size = 1
echo b # 默认值为false
b = on # true的别名
echo b # true
b = off # false的别名
echo b # false
# bool本质上是枚举类型,只可以赋值0或1
b = bool(0)
echo b # 0 = false
b = bool(1)
echo b # 1 = true
# 编译错误
#b = bool(2)
echo sizeof(char) # size = 1,本质上是uint8类型
var c: char = 'a'
echo c
echo ord(c) # 97,ord方法得到字符的ascii码
echo chr(98) # 'b',chr方法将数字转换为字符
var s: string = $c # 将char类型赋值给string类型必须在前面加上美元符号
echo s
var s: string
# 未赋值时是nil
if s == nil:
echo "s == nil"
s = "hello"
echo len(s) # len = 5
echo s[0] # 'h'
echo ord(s[5]) # string以'\0'字符结束
s.add(" 世") # 用add方法在末尾追加字符串
s &= "界" # 字符串之间用'&'符号连接
echo s # hello 世界
严格来讲,Nim并没有Python、C#那样真正的字符串,而是和C/C++中string一样,其本质就是array[char]类型,在Nim中应该表示为seq[char]。所以string硬编码字符串的编码格式取决于源文件编码,一般是utf8
var s = "hello"
echo s.addr.repr
var s2 = s
echo s2.addr.repr
输出:
ref 0042BD1C --> 0095A030"hello"
ref 0042BD14 --> 0095A048"hello"
可见内存地址不同,所以在Nim这里,不像Python、C#那样有不可变数据的说法。
字符串之间的赋值就等同于是数组的完整拷贝,这么做是非常低效的,一定要注意。
如果需要使用引用,可以试试shallowCopy方法
proc foo() =
var s = "hello"
var s2: string
var s3: string
shallowCopy(s2, s)
shallowCopy(s3, s2)
echo s.addr.repr
echo s2.addr.repr
echo s3.addr.repr
foo()
这样3个字符串都指向同一内存了,还可以这样用
proc foo() =
var s = "hello"
s.shallow # 调用之后,赋值操作将会变为传递引用
var s2 = s
var s3 = s2
echo s.addr.repr
echo s2.addr.repr
echo s3.addr.repr
foo()
但shallow也有副作用,编译器在某些情况下可能会忽略掉它,比如全局变量
var s = "hello"
s.shallow
var s2 = s
var s3 = s2
echo s.addr.repr
echo s2.addr.repr
echo s3.addr.repr
同样的代码,从foo函数中挪到全局中,结果三个字符串的地址还是不同
再或者源字符串发生变化,后面的引用的变量是感知不到的
var s = "hello"
s.shallow
var s2 = s
var s3 = s2
echo s.repr
echo s2.repr
echo s3.repr
s.add("world")
echo s.repr
echo s2.repr
echo s3.repr
所以shallow也并非是完美的办法,期待Nim在以后的版本中能提供像Python那样不可变的string。
最后,多行字符串用三个双引号括起来
var
s = """line1
line2
line3"""
echo s
参考:
https://nim-lang.org/docs/tut1.html#basic-types