V语言

V语言学习笔记-02基本类型

2020-05-19  本文已影响0人  lydiandy

布尔类型

bool

bool类型的值只能是true或false


x:=true
y:=false
println(x) //true
println(y) //false
println(sizeof(bool)) //4

bool类型从定义的C代码看,是C的一个int类型别名

true是常量1,false是常量0

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

#ifndef bool
    typedef int bool;
    #define true 1
    #define false 0
#endif

数值类型

整数和小数

类型 长度 取值范围 说明
i8 1字节 -128 到 127 有符号8位整数
i16 2字节 -32,768 到 32,767 有符号16位整数
int 4字节 -2,147,483,648 到 2,147,483,647 int总是32位整数,即i32
i64 8字节 -9223372036854775808到9223372036854775807 有符号64位整数
i128 16字节 未实现 有符号128位整数
byte 1字节 0 到 255 无符号8位整数,即u8
u16 2字节 0 到 65,535 无符号16位整数
u32 4字节 0 到 4,294,967,295 无符号32位整数
u64 8字节 0 到 18446744073709551615 无符号64位整数
u128 16字节 未实现 无符号128位整数
rune 4字节 0 到 4,294,967,295 表示一个unicode码点
f32 4字节 32位小数
f64 8字节 64位小数

数字可以通过前缀标识对应的进制

也可以增加下划线,进行视觉上的分隔,不影响本来的值

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

强制类型转换


字符串类型

string

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

单引号和双引号都可以

习惯上都还是使用单引号,V编译器中的代码都是统一使用的单引号,按作者的说法是可以少按一个shift键,更自然简单一些,不过打破了之前C的使用习惯,让人一开始有些不习惯

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

s1:='abc'
s2:="abc"

字符串长度:

s:='abc'
println(s.len) //输出3

字符串连接:

s1:='abc'
s2:='def'
s3:=s1+s2

字符串追加:

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

字符串插值:

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

遍历字符串:

str:='abcdef'
//遍历value
for s in str {
    println(s.str())
}
//遍历index和value
for i,s in str {
    println('index:$i,value:${s.str()}')
}

字符串切片/区间:

采用的是左闭右开

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

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

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

单字符类型

用反引号来表示单字符类型,跟字符串不是同一个类型,单字符类型对应的是byte类型

s1:='a' //单引号,字符串类型
s2:="aa" //双引号,也是字符串类型

c1:=`a` //反引号,字符类型,单字符
// c2:=`aa` //编译不通过,报错,只能是单字符
// c2:=`中` //编译不通过,报错,只能是单字符
println(s1) //输出a
println(s2) //输出aa
println(c1) //输出97
println(c1.str()) //通过str()函数转换为字符串后,输出a

常用字符串内置函数,可以参考后面的标准库章节,也可以直接参考vlib/builtin/string.v源代码


指针类型

byteptr: 字节类型指针

voidptr: 通用指针,可以指向任何类型

intptr: 整型类型指针

charptr: 字符类型指针

V代码中使用的最多的是byteptr和voidptr

V代码中比较少用intptr,charptr,只有在跟C代码集成时或底层代码用得多,C的很多字符串都是charptr指针

以下是4种指针类型,生成C代码对应的类型定义:

typedef unsigned char* byteptr;
typedef int* intptr;
typedef void* voidptr;
typedef char* charptr;

指针本身占用的内存大小:就是C语言里面的size_t类型,通常在32位系统上的长度是32位,64位系统上是64位

    //测试机器是64位操作系统
    println(sizeof(voidptr)) //输出8个字节
    println(sizeof(byteptr)) //输出8个字节
    println(sizeof(charptr)) //输出8个字节
    println(sizeof(intptr))  //输出8个字节

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

指针类型前加*表示取地址对应的值

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

正常情况下,由V创建的变量,因为声明和初始化一定是同时进行的,所以变量一定会有初始值,所以V指针一定不会有空值,即0值

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

fn main() {
    a := 1
    println(isnil(&a)) //返回false,变量只能通过:=来初始化,一定会有初始值
        
    f := C.popen(cmd.str, 'r') //但是通过调用C代码返回的指针,有可能是空指针,所以在使用前可以用isnil函数来判断一下
    if isnil(f) {
        println(sframe)
        continue
    }
}

在V语言中,指针只是表示引用,跟go指针类型基本一致,不能进行指针运算

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

详细内容可以参考:不安全代码

类型占用内存大小sizeof()

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

println(sizeof(int)) //4
println(sizeof(byte)) //1
println(sizeof(bool)) //4

变量类型typeof()

使用内置函数typeof(var)来返回变量的类型

module main

struct Point {
    x int
}
type MySumType = int | f32 | Point

type MyFn fn(int) int
type MyFn2 fn()

fn myfn(i int) int {
    return i
}
fn myfn2() {
    
}

fn main() {
    a := 123
    s:='abc'    
    aint := []int
    astring := []string
    astruct_static := [2]Point
    astruct_dynamic := [Point{}, Point{}]
    println(typeof(a)) //int
    println(typeof(s))  //string
    println(typeof(aint)) //array_int
    println(typeof(astring)) //array_string
    println(typeof(astruct_static)) //[2]Point
    println(typeof(astruct_dynamic)) //array_Point

    //联合类型也可以判断具体的类型
    sa := MySumType(32)
    sb := MySumType(123.0)
    sc := MySumType(Point{x:43})
    println(typeof(sa))   //int
    println(typeof(sb)) //f32
    println(typeof(sc)) //Point

    //函数类型
    println(typeof(myfn)) //fn (int) int
    println(typeof(myfn2)) //fn ()
}

类型推断及类型转换

module main

fn main(){
    i:=8 //默认类型推断为int
    b:=byte(8) //明确指定类型为byte
    ii:=int(b) //强制转换为int

    f:=3.2 //默认推断类型为f64
    ff:=f32(3.2) //明确指定类型为f32
    f3:=f64(f) //强制转换为f64

    s:='abc' //默认推断为string  
    c:=`c` //默认推断为byte,也就是单字符类型
    ss:=string(&c,1) //强制转换为string,因为string(byteptr,int)就可以构造出一个字符串,其中byteptr是首字节指针,int是字符串长度
    
  //将字节数组转成字符串
    mut byte_arr:=[]byte //字节数组
    byte_arr<<`a`
    byte_arr<<`b`
    println(byte_arr) //输出[a,b]
    str:=string(byte_arr,byte_arr.len) //将字节数组转成字符串
    println(str) //输出ab    
}
上一篇 下一篇

猜你喜欢

热点阅读