在之前的文章《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 ],则该表达式是索引折叠表达式。 它通常的形式是:

c语言用双重指针在无需返回的情况下于函数中创建链表_c语言bool函数怎么用_用c语言画函数图形

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。 这也适用于可变长度数组。

c语言用双重指针在无需返回的情况下于函数中创建链表_用c语言画函数图形_c语言bool函数怎么用

约束

代码示例

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对这些数组元素进行多线程并行操作。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注