bool,布尔类型,值只能是true或false.

    布尔类型从定义的C代码看是byte(uint8_t)的类型别名.

    true是常量1,false是常量0.

    使用sizeof(bool)可以看到bool类型的长度是1个字节.

    1. ...
    2. #ifndef bool
    3. typedef byte bool;
    4. #define true 1
    5. #define false 0
    6. #endif

    数值类型

    数值类型分为整数和小数.

    整数

    小数

    类型 长度 取值范围 说明
    f32 4字节 32位小数
    f64 8字节 64位小数

    数字可以通过前缀标识对应的进制,也可以增加下划线,进行视觉上的分隔,不影响本来的值.

    1. mut c := 0xa_0 //十六进制数字a0
    2. println(c) //输出160
    3. c = 0b10_01 //二进制数字1001
    4. println(c) //输出9
    5. c = 1_000_000 //十进制数字1000000
    6. println(c) //输出1000000

    如果不希望由编译器自动类型推断,可以通过T(value)的格式,显式声明变量类型,T是类型,value是变量值.

    1. x:=i64(3) //x是i64类型,而不是默认推断的int
    2. y:=f32(3.0) //y是f32类型,而不是默认推断的f64

    字节类型

    1. module main
    2. fn main() {
    3. b := byte(98)
    4. println(b.str()) // 98
    5. println(b.ascii_str()) // b
    6. }

    string字符串类型,字符串是一个只读字节数组,默认不可变,UTF-8编码.

    单引号和双引号都可以,习惯上都还是使用单引号,V编译器中的代码都是统一使用的单引号.

    按作者的说法是可以少按一个shift键,更自然简单一些,不过打破了之前C的使用习惯,让人一开始有些不习惯.

    当使用双引号的时候,编译器会自动把双引号自动替换为单引号.

    1. s1:='abc'
    2. s2:="abc"
    1. s:='abc'
    2. println(s.len) //输出3

    字符串连接:

    字符串追加:

    1. mut s:='hello ' //必须是可变才可以追加
    2. s+='world'
    3. println(s) //输出hello world

    字符串插值:

    1. name:='Bob'
    2. println('hello $name') //方式1
    3. println('hello ${name}') //方式2,效果一样,更常用于复杂的表达式,把表达式放在{}里面

    判断字符串是否包含子字符串:

    1. fn main() {
    2. s:='abcd'
    3. println(s.contains('c')) //true
    4. println(s.contains('bc')) //true
    5. println(s.contains('bb')) //false
    6. }

    遍历字符串:

    1. str := 'abcdef'
    2. for s in str {
    3. println(s.str())
    4. }
    5. //遍历index和value
    6. for i, s in str {
    7. println('index:$i,value:$s.str()')

    字符串切片/区间:

    采用的是左闭右开.

    1. s:='hello_world'
    2. println(s[..3]) //输出hel
    3. println(s[2..]) //输出llo_world
    4. println(s[2..5]) //输出llo

    字符串从定义的v代码看,也是一个struct.

    1. pub struct string {
    2. pub: //pub表示这两个字符串的属性都是:公共且只读的
    3. str &byte //一个byte类型的指针,指向字符串的首字节地址
    4. len int //字符串的长度
    5. }

    字符串单引号和双引号混合使用

    主要的逻辑是:

    • 以单引号为主要使用的符号,双引号也可以使用.
    • 如果有字符串嵌套使用,内外必须不能同时是单引号或者同时是双引号,不然无法正确配对.
    • 如果有加上反斜杠进行转义,则都可以.

    rune类型

    rune是u32的类型别名,用4个字节来表示一个unicode字符/码点,跟string不是同一个类型.

    rune使用反引号来表示.

    1. module main
    2. fn main() {
    3. s1 := 'a' //单引号,string类型
    4. s2 := 'a' //双引号,string类型
    5. s3 := `a` //反引号,rune类型
    6. println(typeof(s1).name)
    7. println(typeof(s2).name)
    8. println(typeof(s3).name)
    9. println(int(s3)) // 97
    10. //
    11. // c2 := `aa` //编译不通过,报错,只能是单字符
    12. c3 := `中`
    13. println(typeof(c3).name) // rune类型
    14. println(sizeof(c3)) // 4个字节,unicode4.0
    15. println(int(c3)) // 20013
    16. println(c3)
    17. }

    voidptr指针类型,用来存储变量的内存地址.

    指针本身占用的内存大小就是C语言里面的size_t类型.

    通常在32位系统上的长度是32位,64位系统上是64位.

    1. module main
    2. fn main() {
    3. //测试机器是64位操作系统
    4. println(sizeof(voidptr)) //输出8个字节
    5. }

    变量前加&表示取内存地址,返回指针类型.

    指针类型前加*表示取内存地址对应变量的值.

    1. fn main() {
    2. a := 'abc'
    3. println(&a) // 取变量地址,返回地址
    4. b := &a
    5. println(*b) // 取指针对应的值,返回abc
    6. }

    正常情况下,由V创建的变量,因为声明和初始化一定是同时进行的,

    所以变量一定会有初始值,V指针一定不会有空值,即0值.

    内置函数中的isnil(ptr),是用来判断由C代码生成的指针,是否是空指针.

    1. a := 1
    2. println(isnil(&a)) // 返回false,变量只能通过:=来初始化,一定会有初始值
    3. // 但是通过调用C代码返回的指针,有可能是空指针,所以在使用前可以用isnil函数来判断一下
    4. f := C.popen('ls', 'r')
    5. if isnil(&f) {
    6. println('f is nil')
    7. } else {
    8. println('f is not nil')
    9. }
    10. }

    在V语言中,指针只是表示引用,不能进行指针运算.

    只有在unsafe代码块中,V编译器不进行任何检查,允许指针像C那样可以进行指针运算,指针偏移,多级指针.

    详细内容可以参考:.

    类型占用内存大小sizeof()

    使用内置函数sizeof(T)来返回类型占用内存大小.

    1. println(sizeof(int)) //4
    2. println(sizeof(byte)) //1
    3. println(sizeof(bool)) //1
    1. module main
    2. struct Point {
    3. x int
    4. }
    5. type MyFn = fn (int) int
    6. type MyFn2 = fn ()
    7. fn myfn(i int) int {
    8. return i
    9. }
    10. fn myfn2() {
    11. }
    12. fn main() {
    13. a := 123
    14. s := 'abc'
    15. aint := []int{}
    16. astring := []string{}
    17. astruct_static := [2]Point{}
    18. astruct_dynamic := [Point{}, Point{}]
    19. //使用typeof().name获取变量的类型
    20. println(typeof(a).name) // int
    21. println(typeof(s).name) // string
    22. println(typeof(aint).name) // array_int
    23. println(typeof(astring).name) // array_string
    24. println(typeof(astruct_static).name) // [2]Point
    25. println(typeof(astruct_dynamic).name) // array_Point
    26. //函数类型
    27. println(typeof(myfn).name) // fn (int) int
    28. }

    类型推断及类型转换