在之前的文章《C语言为什么不能直接给数组对象赋值》中,作者谈到了在C语言设计之初没有引入数组赋值语法的种种原因。 当然,从它的语法体系来看c语言bool函数怎么用,数组对象作为表达式时,它的类型会被隐式转换为指向它的元素类型的指针,数组本身的引用是不能修改的,所以像下面这样该代码导致语法错误:
int arr1[3] = { 0 };
int arr2[3] = { 0 };
arr1 = arr2; // 相当于:(int * const)arr1 = (int *)arr2;
这是显而易见的。
有没有办法通过某种语法扩展,让C语言中的数组赋值变得简单? 答案是可以设计! 作者这里使用GNU语法扩展中引入的Case Ranges(),结合C++17中完美的折叠表达式,设计了C语言的[ from … to ] 索引折叠表达式(index fold expression)语法扩大。
基本定义
如果表达式包含表达式 [ from … to ],则该表达式是索引折叠表达式。 它通常的形式是:
a[ 0 ... 2 ] = b[ 5 ... 7 ];
相当于:
( a[0] = b[5],
a[1] = b[6],
a[2] = b[7]
);
为了简化编译器的实现,from和to可以限定为常量表达式,即必须是编译时可以确定的常量。 这与 GNU 语法扩展中引入的大小写范围一致。 当[ from … to ]的操作数是数组对象时,可以默认to。 而默认to时c语言bool函数怎么用,其值为sizeof(array) / sizeof(array[0]) – 1U。 这也适用于可变长度数组。
约束
代码示例
int arr1[3] = { 1, 2, 3 };
int arr2[5] = { 1, 2, 3, 4, 5 };
// 相当于:(arr1[0] = arr2[2], arr1[1] = arr2[3], arr1[2] = arr2[4]);
arr1[0 ...] = arr2[2 ...];
// 相当于:int arr3[3] = { arr2[1], arr2[2], arr[3] };
int arr3[] = { arr2[1 ... 3] };
int sum = 0;
// 相当于:(sum += arr1[0], sum += arr1[1], sum += arr[2]);
sum += arr1[0 ...];
// 相当于:(arr1[0] += sum, arr1[1] += sum, arr1[2] += sum);
arr1[0 ...] += sum;
static bool IsLower(int a, int b)
{
return a < b;
}
bool bArr[3];
// 相当于:
// (bArr[0] = IsLower(arr1[0], arr3[0]),
// bArr[1] = IsLower(arr1[1], arr3[1]),
// bArr[2] = IsLower(arr1[2], arr3[2])
// );
bArr[0 ...] = IsLower(arr1[0 ...], arr3[0 ...]);
int FooInc(int arr[static 3])
{
// 相当于:(++arr[0], ++arr[1], ++arr[2]);
// 注意,arr作为函数形参,其本质上属于指针,而不是数组,
// 因此,这里 to 的位置不可缺省!
++arr[0 ... 2];
// 相当于:return (arr[0], arr[1], arr[2]);
// 因此最后其实返回的是 arr[2] 的值。
return arr[0 ... 2];
}
优化
如果对多个数组或被restrict修饰的指针进行操作,编译器后端可以生成SIMD指令或者使用Intel TBB或微软PPL等并行库的parallel_for对这些数组元素进行多线程并行操作。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。