diff --git a/doc/docs.md b/doc/docs.md index b421ce1521..3a326717e1 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -753,6 +753,33 @@ array_2 << array_1[..3] println(array_2) // [0, 1, 3, 5, 4] ``` +### Fixed Size Arrays +V also supports arrays with fixed size. Unlike ordinary arrays, their +length is fixed, so you can not append elements to them, nor shrink them. +You can only modify their elements in place. Note also, that most methods +are defined to work on ordinary arrays, not on fixed size arrays. + +However, access to the elements of fixed size arrays, is more efficient, +they need less memory than ordinary arrays, and unlike ordinary arrays, +their data is on the stack, so you may want to use them as buffers if you +do not want additional heap allocations. + +You can convert a fixed size array, to an ordinary array with slicing: +```v +mut fnums := [3]int{} // fnums is now a fixed size array with 3 elements. +fnums[0] = 1 +fnums[1] = 10 +fnums[2] = 100 +println(fnums) // => [1, 10, 100] +println(typeof(fnums).name) // => [3]int +// +anums := fnums[0..fnums.len] +println(anums) // => [1, 10, 100] +println(typeof(anums).name) // => []int +``` +Note that slicing will cause the data of the fixed array, to be copied to +the newly created ordinary array. + ### Maps ```v diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index be096f7c3c..0e47096c54 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -4000,13 +4000,22 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { g.expr(node.left) } else if sym.kind == .array_fixed { // Convert a fixed array to V array when doing `fixed_arr[start..end]` - g.write('array_slice(new_array_from_c_array(_ARR_LEN(') - g.expr(node.left) - g.write('), _ARR_LEN(') - g.expr(node.left) - g.write('), sizeof(') + info := sym.info as table.ArrayFixed + g.write('array_slice(new_array_from_c_array(') + g.write('$info.size') + g.write(', $info.size') + g.write(', sizeof(') + if node.left_type.is_ptr() { + g.write('(*') + } g.expr(node.left) + if node.left_type.is_ptr() { + g.write(')') + } g.write('[0]), ') + if node.left_type.is_ptr() { + g.write('*') + } g.expr(node.left) g.write(')') } else { @@ -4022,9 +4031,8 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { if node.index.has_high { g.expr(node.index.high) } else if sym.kind == .array_fixed { - g.write('_ARR_LEN(') - g.expr(node.left) - g.write(')') + info := sym.info as table.ArrayFixed + g.write('$info.size') } else if node.left_type.is_ptr() { g.write('(') g.write('*') diff --git a/vlib/v/tests/array_slice_test.v b/vlib/v/tests/array_slice_test.v index ee375cdb41..50141190a7 100644 --- a/vlib/v/tests/array_slice_test.v +++ b/vlib/v/tests/array_slice_test.v @@ -29,6 +29,16 @@ fn test_access_slice_attribute() { assert access_slice_attribute(mut arr) == 4 } +fn fixed_array_slice(a [3]int) { + assert a[0..] == [1, 2, 3] + assert a[..a.len] == [1, 2, 3] +} + +fn mut_fixed_array_slice(mut a [3]int) { + assert a[0..] == [1, 2, 3] + assert a[..a.len] == [1, 2, 3] +} + fn test_fixed_array_slice() { fixed_array1 := [1, 2, 3]! arr1 := fixed_array1[0..] @@ -36,12 +46,14 @@ fn test_fixed_array_slice() { fixed_array2 := [[1, 2], [2, 3], [3, 4],[4, 5]]! arr2 := fixed_array2[0..] assert arr2 == [[1, 2], [2, 3], [3, 4],[4, 5]] + mut arr := [1,2,3]! + fixed_array_slice(arr) + mut_fixed_array_slice(mut arr) } fn pointer_array_slice(mut a []int) { assert a[0..] == [1,2,3] assert a[..a.len] == [1,2,3] - } fn test_pointer_array_slice() {