在 C 中使用数组的指针问题
Issue with pointers using arrays in C
在 C 中使用指针和数组我发现了一个奇怪的案例,我不明白它为什么会发生。
首先,我想描述一下正确的情况:
我定义了一个函数 void modifyArray(int *list)
,其中必须通过引用修改数组以将项目乘以 2 倍 (x2)。函数实现为:
void modifyArray(int *list, int arrLength){
for(int i=0; i<arrLength; i++){
*(list + i) = *(list + i) * 2; // x = x * 2
}
}
int main(int nargs, char **args) {
int list[] = {1,2,3,4,5};
modifyArray(&list, 5);
for(int i=0; i<5; i++){
printf("%d\n", *(list + i));
}
}
输出为:
2
4
6
8
10
现在我要解释不正确的情况:我定义了一个新的数据类型List
并修改了函数以接受List
而不是 int *
或 int[]
作为第一个参数:
typedef int List[5];
void modifyArray(List *list, int arrLength){
for(int i=0; i<arrLength; i++){
*(list + i) = *(list + i) * 2; // x = x * 2
}
}
修改后我的编译器构建失败,因为句子 *(list + i) = *(list + i) * 2; // x = x * 2
can't multiply bacause of the following error message:
Invalid operands to binary expression ('List' (aka 'int [5]') and 'int')
我知道我的编译器正在尝试将整个数组乘以 2,但不知道原因。
我找到的解决方案是用 *(*list + 1)
替换 *(list + 1)
。我很困惑,因为在第二种情况下,当我打印 list
和 *list
输出是一个内存地址(两者的内存地址相同)而不是 list
及其内容的内存地址*list
.
你能解释为什么会这样吗?使用 int *
和 List
定义的类型有什么区别?
当list
定义为int list[] = {1,2,3,4,5};
时,&list
是指向五个int
的数组的指针。将此传递给 int *
类型的参数是不合适的,编译器应该在第一段代码中对此发出警告或错误。正确的参数是 list
。虽然这是一个数组,但它会自动转换为指向其第一个元素的指针,并且该指针是 int *
,这是参数的正确类型。
当参数声明为List *list
时,它是一个指向数组的指针。然后,在 *(list + i)
中,加法是以这些数组为单位而不是以 int
为单位进行的。加法的结果是一个指向数组的指针,所以*(list + i)
中的*
的结果是一个数组。然后乘法试图将一个数组乘以二,所以编译器会报错。
相反,将参数声明为 List list
。这声明它是一个数组,但它会自动调整为指向 int
的指针。因为 C 不支持将数组作为参数传递,所以它会自动将参数声明调整为数组元素指针声明,而不是支持。
另外,不要写*(list + i)
。使用 list[i]
。它的意思相同,但更容易阅读。
在 C 中使用指针和数组我发现了一个奇怪的案例,我不明白它为什么会发生。
首先,我想描述一下正确的情况:
我定义了一个函数 void modifyArray(int *list)
,其中必须通过引用修改数组以将项目乘以 2 倍 (x2)。函数实现为:
void modifyArray(int *list, int arrLength){
for(int i=0; i<arrLength; i++){
*(list + i) = *(list + i) * 2; // x = x * 2
}
}
int main(int nargs, char **args) {
int list[] = {1,2,3,4,5};
modifyArray(&list, 5);
for(int i=0; i<5; i++){
printf("%d\n", *(list + i));
}
}
输出为:
2
4
6
8
10
现在我要解释不正确的情况:我定义了一个新的数据类型List
并修改了函数以接受List
而不是 int *
或 int[]
作为第一个参数:
typedef int List[5];
void modifyArray(List *list, int arrLength){
for(int i=0; i<arrLength; i++){
*(list + i) = *(list + i) * 2; // x = x * 2
}
}
修改后我的编译器构建失败,因为句子 *(list + i) = *(list + i) * 2; // x = x * 2
can't multiply bacause of the following error message:
Invalid operands to binary expression ('List' (aka 'int [5]') and 'int')
我知道我的编译器正在尝试将整个数组乘以 2,但不知道原因。
我找到的解决方案是用 *(*list + 1)
替换 *(list + 1)
。我很困惑,因为在第二种情况下,当我打印 list
和 *list
输出是一个内存地址(两者的内存地址相同)而不是 list
及其内容的内存地址*list
.
你能解释为什么会这样吗?使用 int *
和 List
定义的类型有什么区别?
当list
定义为int list[] = {1,2,3,4,5};
时,&list
是指向五个int
的数组的指针。将此传递给 int *
类型的参数是不合适的,编译器应该在第一段代码中对此发出警告或错误。正确的参数是 list
。虽然这是一个数组,但它会自动转换为指向其第一个元素的指针,并且该指针是 int *
,这是参数的正确类型。
当参数声明为List *list
时,它是一个指向数组的指针。然后,在 *(list + i)
中,加法是以这些数组为单位而不是以 int
为单位进行的。加法的结果是一个指向数组的指针,所以*(list + i)
中的*
的结果是一个数组。然后乘法试图将一个数组乘以二,所以编译器会报错。
相反,将参数声明为 List list
。这声明它是一个数组,但它会自动调整为指向 int
的指针。因为 C 不支持将数组作为参数传递,所以它会自动将参数声明调整为数组元素指针声明,而不是支持。
另外,不要写*(list + i)
。使用 list[i]
。它的意思相同,但更容易阅读。