C语言中指针的问题

5

我有这段代码:

#include <stdio.h>
int arraySum (int *a, int n);
int main(void){
    int values[3] = {1, 2, 3};
    printf("The sum is %i\n", arraySum(values, 3));
    return 0;
}
int arraySum(int *a, int n){
    int sum = 0;
    int arrayEnd = *a + n;
    for ( ; *a < arrayEnd; *a++)
        sum += *a;
    return sum;
}

由于某些原因,它输出了这个:
roman@lmde64 ~/Dropbox/Practice $ gcc practice.c 
roman@lmde64 ~/Dropbox/Practice $ ./a.out
The sum is -421028781
roman@lmde64 ~/Dropbox/Practice $ ./a.out
The sum is -362865581
roman@lmde64 ~/Dropbox/Practice $ ./a.out
The sum is -1046881197
roman@lmde64 ~/Dropbox/Practice $ ./a.out
The sum is 6
roman@lmde64 ~/Dropbox/Practice $ ./a.out
The sum is 6

有时输出结果是奇怪的数字,有时则是正确答案。我做错了什么吗?感谢任何帮助。

2
只是提醒一下……你知道指针可以使用数组表示法吗?这是一种非常复杂的访问数组元素的方法,而不是:for(int arrayIndex = 0; arrayIndex < n; arrayIndex++) { sum += a[arrayIndex]; } - Dancrumb
不,我没有。谢谢你的提示。 - lqdc
5个回答

14

arraySum() 函数中,你混淆了何时使用 a 作为指针以及何时解引用它以获取它所指向的内容。当你计算循环限制等操作时,你希望使用指针本身:

int arraySum(int *a, int n){
    int sum = 0;
    int *arrayEnd = a + n;
    for ( ; a < arrayEnd; a++)
        sum += *a;
    return sum;
}

虽然这并没有解释非确定性行为。据我所知,程序完全合法,实际上应该输出6。 - Fred Foo

2
您想遍历数组:
int arraySum(int *a, int n){
    int sum = 0;
    int * arrayEnd = a + n; // arrayEnd points to the first element after your array a
    for ( ; a != arrayEnd; ++a)  // Iterate over the array until you reach arrayEnd
        sum += *a; // Dereference the pointer to current array element in order to retrieve a value
    return sum;
}

1
int arraySum(int *a, int n) {
   int sum = 0;
   for (int i = 0; i < n; ++i)
      sum += a[i];
   return sum;
}

或者

int arraySum(int *a, int n) {
   int sum = 0;
   for (int i = 0; i < n; ++i)
      sum += *a++;
   return sum;
}

1
  • *a++*(a++) 是一样的;在这个例子中,* 没有起到任何作用
  • arrayEnd 被设置为 *a + 3,或者 1 + 3,或者 4
  • 你的 for 循环在数组耗尽之前没有终止。访问超出数组限制会引发未定义行为
  • 你的程序也可能输出 "The mighty sum is not what you expect!\n"

我的理解是*a++会获取a所指向的int值,然后将a递增。 - Richard Schneider
是的,@Richard;*a++ 的值就像你说的那样。问题在于它在 for 循环中什么也没做:更简单的 a++ 就足够了。 - pmg
好的,那么为什么当我使用int * arrayEnd = a + n;而不是只使用arrayEnd时,它会正确终止呢? - lqdc
1
@lqdc:因为这样你就要处理指针而不是整数。a是一个指针;*a是一个整数;a + n是一个指针(指向距离a的整数n);*a + n是一个整数。 - pmg

1

在原始代码中,

  • *a + n 的值为 1+3 = 4
  • 在每次for循环迭代中,指向的*a的值与4进行比较。
  • 如果*a的值小于4,则计算sum
  • 经过3次迭代后,a指向values[2],即3。稍后,当a被递增时, 它指向value[2]之外的地址--这个地址可能包含任何垃圾值。 如果垃圾值小于4,它将计算sum。这种行为会一直持续,直到遇到大于4的值。 因此,sum的值有时是6或其他垃圾值

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接