Skip to content

struct ​

struct 把若干字段打包成一块连续的值内嵌存储。CIN 的 struct 没有指针、没有方法、没有构造函数:StructName s 声明即得到一块全零的存储。

定义语法 ​

text
struct 名称 {
    类型 字段名
    类型 字段名[固长维度]
    ...
}
cin
struct Point {
    float x
    float y
}

struct Rectangle {
    Point top_left        // 嵌套 struct: 值内嵌
    Point bottom_right
    float area
}

字段之间以换行或 ; 分隔,字段可以带固长数组维度(int grades[5]),但数组元素必须是标量——Point items[3] 这类 struct 元素数组不能作字段,见 字段限制。struct 定义只描述布局,本身不产生存储;存储来自变量声明。

cin
struct Point { int x
    int y }

function main() -> int {
    Point p
    p.x = 3
    p.y = 4
    println(int_to_str(p.x) + "," + int_to_str(p.y))   // 3,4
    return p.x
}

成员访问:点号 ​

成员访问统一使用 .,支持链式:

cin
struct Point { float x
    float y }

struct Rectangle {
    Point top_left
    Point bottom_right
}

function area(Rectangle r) -> float {
    float w = r.bottom_right.x - r.top_left.x
    float h = r.bottom_right.y - r.top_left.y
    return w * h
}

function main() -> int {
    Rectangle box
    box.top_left.x = 0.0
    box.top_left.y = 0.0
    box.bottom_right.x = 3.0
    box.bottom_right.y = 4.0
    println("area = " + area(box))     // area = 12
    return 0
}
  • 多层嵌套可以一直点下去:box.bottom_right.x。
  • 对非 struct 类型取成员会报 Member access on non-struct type: int。
  • 字段名拼错会报 Struct X has no field Y(例如 Struct P has no field y)。

嵌套 struct:值内嵌 ​

嵌套 struct 的字段内嵌存储,不是指针——外层 struct 的槽数包含所有内层字段。

定义说明
Point top_left内嵌一个完整 Point(两个 float 槽)
int grades[5]✅ 标量元素的固长数组字段(值内嵌)
Point corners[2]❌ 编译期报错:struct 元素固长数组不能作字段(见 字段限制)
string name一个指针槽(字符串本身在堆上)
cin
struct Inner { int a
    int b }

struct Outer {
    Inner i1
    Inner i2
    int tag
}

function main() -> int {
    Outer o
    o.i1.a = 1
    o.i2.b = 2
    o.tag = 9
    println(int_to_str(o.i1.a) + int_to_str(o.i1.b)
            + int_to_str(o.i2.a) + int_to_str(o.i2.b)
            + int_to_str(o.tag))        // 10029
    return 0
}

聚合初始化:花括号 ​

声明 struct 变量时可以用花括号一次性给字段赋值,按字段声明顺序逐个对应:

cin
struct P { int x
    int y }

function main() -> int {
    P p = {3, 4}                     // p.x = 3, p.y = 4
    println(int_to_str(p.x) + "," + int_to_str(p.y))     // 3,4
    return 0
}
写法说明
P p = {3, 4}按声明顺序写字段
P q = {9}字段不足时其余字段保持默认值(这里是 q.y == 0,因为对象已全零)
Out o = { {5, 6}, 7}嵌套 struct 用嵌套花括号;内层也可以省略(摊平后按叶子字段顺序对应)
P ps[2] = { {1, 2}, {3, 4} }struct 数组:每个元素一个花括号
P ps[2] = {1, 2}元素不足时其余元素保持默认(全零),等价于只初始化 ps[0]

字段不足是允许的(其余取默认值),初始化器过多是编译期错误:

text
Compiler error: Too many initializers for struct P: got 3, expected at most 2
Compiler error: Too many initializers for struct array ps: got 3, expected at most 2
  • 每个值都按目标字段类型转换:int 字段收到 3.7 会向零截断为 3;
  • 全局 struct 的聚合初始化同样要求常量表达式,否则报 Non-constant global initializer: var;局部可以写任意表达式;
  • 初始化只作用于对象自身的槽,不改变值语义:P b = {1, 2} 得到的仍是一个与任何 其它对象互不影响的新对象。

顺序 = 字段声明顺序,没有指定初始化器

CIN 没有 C 那样的 {.y = 4} 具名初始化器,所以 {3, 4} 永远按 struct 里字段出现的 顺序对应。调整字段声明顺序会同时改变所有聚合初始化器的含义,跟 C 一样要注意。

值语义:整体赋值、传参、返回 ​

操作语义示例
整体赋值 P b = a / b = a值拷贝(逐槽复制到各自对象),之后互不影响b.x = 7 不改 a.x
作为函数参数引用可见(同一块存储,不复制)函数内 p.x = 99 调用方可见
作为返回值值拷贝返回:每次调用都是新对象两次 make(4) 得到互不影响的两个对象
作为 struct 数组元素每个元素是独立的完整 struct 对象P ps[3] 是 3 份完整 P;ps[1] = ps[0] 同样是值拷贝
作为数组参数元素引用可见函数内 ps[0].x = 1 可见
cin
struct P { int x }

function main() -> int {
    P a
    a.x = 5
    P b = a          // 拷贝
    b.x = 7
    println(int_to_str(a.x) + " " + int_to_str(b.x))   // 5 7
    return 0
}

语义有别,别混淆

P b = a 是拷贝(写 b 不动 a);把 P 交给函数是引用(函数写 p 会动到 a)。 如果希望函数不改动调用方,请传标量字段,或在函数内先自行拷一份。

固长数组字段 ​

字段可以是固长数组,数组元素是标量时值内嵌在 struct 里(_type_slots 会按 维度 × 元素槽数 展开)。

cin
struct Student {
    int grades[5]         // 固长数组字段(值内嵌)
    float gpa
}

function main() -> int {
    Student s
    for (int i = 0; i < 5; i = i + 1) {
        s.grades[i] = 60 + i * 10
    }
    s.gpa = 88.5
    println(int_to_str(s.grades[0]) + " "
            + int_to_str(s.grades[4]) + " "
            + float_to_str(s.gpa))       // 60 100 88.5
    return 0
}

多维固长数组字段同样支持:

cin
struct Grid {
    int cell[3][4]        // 行主序
    int rows
}

struct 元素的固长数组字段不受支持

struct Bag { Point items[3] } 会在编译期直接失败(而不是留到运行期出错):

text
Compiler error: struct array field Bag.items is not supported (elements would need
separate objects); use a fixed array of struct variables instead

原因是每个 struct 元素都是独立对象,没法内嵌在父对象的一段连续槽里。替代写法是把 数组提升为独立的 struct 数组变量,让每个元素各自成为完整对象,需要成组传递时再用 下标关联(或自己维护一个计数字段):

cin
struct Point { int x
    int y }

Point items[3]            // 独立 struct 数组变量: 3 个完整的 Point

function main() -> int {
    items[0].x = 1
    items[0].y = 2
    items[2].x = 5
    println(int_to_str(items[0].x) + "," + int_to_str(items[0].y)
            + " " + int_to_str(items[1].x) + " " + int_to_str(items[2].x))   // 1,2 0 5
    return 0
}

标量数组字段(int grades[5]、int cell[3][4])不受影响,照常可用。

字段限制 ​

允许的字段说明
标量 int float bool stringstring 本身只占一个指针槽
嵌套 struct值内嵌,占满内层全部槽
固长数组 T[n]、T[n][m](元素为标量)值内嵌,占 n × 元素槽数
不支持的用法说明
struct 元素的固长数组字段 Point items[3]编译期报错 struct array field X.items is not supported;改用独立的 struct 数组变量(见上)
变长指针数组字段 T[]官方限制,不要依赖(见 docs/CIN_GUIDE.md §14 限制 5);需要变长集合请用固长数组上限 + 长度字段
字段带初始化器字段只声明类型与名字,没有默认初始化表达式
方法 / 构造函数 / 继承语言不提供,用普通函数接收 struct 实现
取字段地址(&s.x)语言无取地址运算

变长指针数组字段

struct Bag { int[] items } 这类写法不在受支持范围内。请改写为定长容量 + 计数字段:

cin
struct Bag {
    int items[64]        // 容量固定
    int count            // 实际使用数量
}

实例化与默认全零 ​

StructName 变量名 声明即分配存储,所有字段默认为类型默认值(int → 0、float → 0.0、bool → false、string → 空串、嵌套 struct 递归全零);这块存储由编译器显式清零,不是"碰巧是新的堆内存"。

cin
struct Point { int x
    int y
    string label
    bool visible }

function main() -> int {
    Point p
    println(int_to_str(p.x) + " " + int_to_str(p.y))   // 0 0
    println("[" + p.label + "]")                       // []
    println("visible=" + bool_to_str(p.visible))       // visible=false
    return 0
}
  • 全局 struct 变量默认同样全零;要非零初值就写常量聚合初始化器 (Point origin = {1, 2}),非常量表达式仍报 Non-constant global initializer: var。
  • 局部 struct 变量在进入所在块时分配对象并显式清零:编译器发出 MALLOC 后逐槽写 0, 不依赖"堆恰好是新的"内存。因此局部 struct 的字段默认值可靠;局部标量与局部固长 数组则不然 —— 那两者是栈帧残留值(见 变量与作用域 · 默认值)。 离开块后对象释放。
cin
struct Point { int x
    int y }

function main() -> int {
    Point p           // 进入块时分配对象并清零
    p.x = 1
    return p.x
}

完整示例:Point / Rectangle / Student ​

cin
// shapes.cin —— 运行: codecin shapes.cin

struct Point {
    float x
    float y
}

struct Rectangle {
    Point top_left
    Point bottom_right
    float area
}

struct Student {
    string name
    int age
    int grades[5]
    float gpa
}

// 参数是 struct: 引用可见
function compute_area(Rectangle r) {
    float w = r.bottom_right.x - r.top_left.x
    float h = r.bottom_right.y - r.top_left.y
    r.area = w * h
}

// 返回值是 struct: 值拷贝
function make_student(string name, int age) -> Student {
    Student s
    s.name = name
    s.age = age
    for (int i = 0; i < 5; i = i + 1) {
        s.grades[i] = 60 + (i + 1) * 5
    }
    s.gpa = 88.5
    return s
}

function average(Student s) -> float {
    float sum = 0.0
    for (int i = 0; i < 5; i = i + 1) {
        sum = sum + s.grades[i]
    }
    return sum / 5.0
}

function main() -> int {
    Rectangle box
    box.top_left.x = 0.0
    box.top_left.y = 0.0
    box.bottom_right.x = 4.0
    box.bottom_right.y = 5.0
    compute_area(box)                       // 引用可见, box.area 被写入
    println("area = " + float_to_str(box.area))       // area = 20

    Rectangle copy = box                    // 值拷贝
    copy.top_left.x = 1.0
    println("orig.x = " + float_to_str(box.top_left.x)
            + " copy.x = " + float_to_str(copy.top_left.x))   // 0 1

    Student s = make_student("Ada", 18)
    println(s.name + " age=" + int_to_str(s.age)
            + " g0=" + int_to_str(s.grades[0])
            + " g4=" + int_to_str(s.grades[4]))
    println("avg = " + float_to_str(average(s)))      // avg = 75

    return int_to_str(box.area) == "20" ? 0 : 1
}

预期输出:

text
area = 20
orig.x = 0 copy.x = 1
Ada age=18 g0=65 g4=85
avg = 75

常见 struct 错误 ​

错误信息原因修正
Struct P has no field y访问了不存在的字段检查字段名拼写
Member access on non-struct type: int对 int/float 用 .只有 struct 变量能用 .
Undefined variable: sstruct 变量未声明先 Point s 声明
struct array field Bag.items is not supportedstruct 元素数组不能作字段改用独立的 struct 数组变量(见 字段限制)
Too many initializers for struct P: got 3, expected at most 2聚合初始化器多于字段删掉多余的初始化器;缺省字段会自动取默认值
Non-constant global initializer: var全局 struct 用了非常量初始化全局只写常量聚合初始化器,或在函数内赋值
Expected RBRACE ... at line N字段块括号不配对检查 struct 定义

相关页面 ​

主题说明页面
类型系统各类型默认值与槽数类型系统
函数struct 传参与返回函数
数组固长数组与指针数组数组
字符串string 字段的指针语义字符串
标准库matrix.cin / queue.cin 等库内 struct 用法标准库总览
限制与错误struct 字段限制原文限制与常见错误

文档由 VitePress 构建