关于C++数组与整数相加及Block Swap算法参数传递的技术疑问
Block Swap算法数组旋转的C++代码与技术疑问解答
先来看这段用于实现数组旋转的Block Swap算法C++代码(来自GeeksforGeeks的相关实现):
#include <bits/stdc++.h> using namespace std; /*Prototype for utility functions */ void printArray(int arr[], int size); void swap(int arr[], int fi, int si, int d); void leftRotate(int arr[], int d, int n) { /* Return If number of elements to be rotated is zero or equal to array size */ if(d == 0 || d == n) return; /*If number of elements to be rotated is exactly half of array size */ if(n - d == d) { swap(arr, 0, n - d, d); return; } /* If A is shorter*/ if(d < n - d) { swap(arr, 0, n - d, d); leftRotate(arr, d, n - d); } else /* If B is shorter*/ { swap(arr, 0, d, n - d); leftRotate(arr + n - d, 2 * d - n, d); /*This is tricky*/ } } /*UTILITY FUNCTIONS*/ /* function to print an array */ void printArray(int arr[], int size) { int i; for(i = 0; i < size; i++) cout << arr[i] << " "; cout << endl; } /*This function swaps d elements starting at index fi with d elements starting at index si */ void swap(int arr[], int fi, int si, int d) { int i, temp; for(i = 0; i < d; i++) { temp = arr[fi + i]; arr[fi + i] = arr[si + i]; arr[si + i] = temp; } } // Driver Code int main() { int arr[] = {1, 2, 3, 4, 5, 6, 7}; leftRotate(arr, 2, 7); printArray(arr, 7); return 0; } // This code is contributed by Rath Bhupendra
这段代码运行后会输出3 4 5 6 7 1 2,符合预期。针对你提出的两个技术疑问,我来逐一解答:
疑问1:在leftRotate函数的else分支中,传递参数arr+n-d时,是否属于C++中“将整数与数组相加”的操作?
准确来说,这不是整数和数组相加,而是指针与整数的算术操作。
在C++中,当数组名(比如这里的arr)出现在表达式中(除了少数例外情况,比如用sizeof(arr)、&arr的时候),会被隐式转换为指向数组第一个元素的指针(也就是int*类型)。所以arr + n - d本质是把指向数组首元素的指针,加上偏移量n-d,最终得到的是指向数组中第n-d个元素的指针(下标从0开始计数,对应arr[n-d]的地址)。
疑问2:如何在C++中实现整数与数组相加?我曾在在线编译器尝试该操作但未成功,为何上述代码却能正常运行?
首先要明确:你不能直接将整数和数组类型(比如int arr[])相加——数组本身是一种聚合类型,不是指针,只有在特定场景下数组名会退化为指针。
你尝试失败的原因大概率是在数组名没有退化为指针的场景下做加法,比如:
- 如果你写了
arr + 5但此时arr处于sizeof(arr)这类保持数组类型的语境中,就会报错; - 或者你尝试把数组名当作数组类型直接赋值给非指针变量后再做加法,也会触发错误。
而代码中arr + n -d能正常运行的原因是:
当数组名arr作为实参传递给leftRotate函数的int arr[]形参时,C会自动把形参arr解析为int*类型(也就是指针)。所以此时在函数内部使用arr + n -d,本质是对指针做算术操作,完全符合C的语法规则,因此可以正常运行。
简单总结:数组名在多数表达式和函数参数传递场景下会退化为指针,此时和整数相加是合法的指针偏移操作;但如果数组名保持其数组类型(比如sizeof、取地址&arr),就不能和整数相加。
内容的提问来源于stack exchange,提问作者gm lohith




