如何将一个整数数组作为参数传递给函数并修改内容?

时间:2016-02-05 18:38:32

标签: c arrays

我试图通过函数修改整数数组,但数组保持其原始值。我试图访问它的值来修改它:

这会产生错误:

*array[i] = *array[i] * *array[i];

此示例运行程序但数组将被修改:

int main() {
    int array[] = {1, 2, 3, 4, 4, 5, 6};
    int size = sizeof(array)/sizeof(int); 
    square_array_values(&array, size);
}

void square_array_values(int *array, int size) {
    int i;
    for (i = 0; i < size; i++) {
        printf("Array[%d]: %d.\n", i, array[i]);
        array[i] = array[i] * array[i];
    }
}

4 个答案:

答案 0 :(得分:3)

对于数组,数组名称本身是数组的基址。因此,对于您的示例,您只需将(array)发送到函数。

由于将数组发送到某个函数将它们衰减为指针,它将与square_array_values()

的实现完美配合

更改为

square_array_values(array, size);

我不经常这么说,但是因为我心情很好。

始终做

int main(void)

而不是

int main()

int main()表示main可以接受任意数量的参数。

答案 1 :(得分:2)

您不应该传递数组的地址,因为数组本身会转换为指针。只需改变这个

square_array_values(&array, size);

square_array_values(array, size);

没有&运算符的地址,使用它时,您传递的指针的类型为int (*)[],而不是int *,这就是您所需要的。

此外,您可以启用编译器警告,并且应发出不兼容类型警告。

答案 2 :(得分:2)

将数组的地址传递为&array是不正确的,您应该直接传递数组,编译器会自动将指针传递给它的第一个元素。这称为衰减

您观察到数组保持不变,但请再想一想:在>修改之前打印每个数组元素的内容。将代码更改为:

void square_array_values(int *array, int size) {
    int i;
    for (i = 0; i < size; i++) {
        array[i] = array[i] * array[i];
        printf("Array[%d]: %d.\n", i, array[i]);
    }
}

请按照以下步骤操作:

  • 重新编译并验证数组是否确实已修改。
  • 然后在square_array_values之前移动main的定义并再次编译:您应该收到有关类型不匹配的警告。
  • 最后将来自square_array_values(array, size);的呼叫网站和return 0;中的main修复。

答案 3 :(得分:1)

这对答案方来说已经很晚了 - 我希望它能为您提供一些关于如何在代码中添加打印件以帮助显示正在发生的事情的想法。

考虑以下程序的输出。有几种方法可以解决这个问题,这只是一种可能性。所有早期的答案都很扎实,应该给你一些好主意。

您将需要建立内存分配在C中的工作原理模型,以便您可以预测编译器将执行的操作。我发现打印变量值及其地址通常很有帮助。您可以使用纸和笔勾画“记忆图”,以便了解哪些变量引用了哪个存储。

Foo.c输出

$ gcc Foo.c
$ ./a.out
hello from main(), size=7
array1= 0x7ffc36ef7da0, &(array1)= 0x7ffc36ef7da0
  Note that &(array1[0]) equals both the value of array1 and &(array1), above.
  Also, each subsequent address of array1's elements is sizeof(int) = 4 more
  than the previous element, e.g. &(array[N]) = &(array[N-1]) + 4)
   ---- before, array1 ----
   array1[0]=1            |  0x7ffc36ef7da0
   array1[1]=2            |  0x7ffc36ef7da4
   array1[2]=3            |  0x7ffc36ef7da8
   array1[3]=4            |  0x7ffc36ef7dac
   array1[4]=5            |  0x7ffc36ef7db0
   array1[5]=6            |  0x7ffc36ef7db4
   array1[6]=7            |  0x7ffc36ef7db8
array2=       0x400b0d, &(array2)= 0x7ffc36ef7d98
   We haven't allocated array2 yet, so no contents to print out.
   In fact, we Really Shouldn't be printing what array2 'points' to at all,
   but (when it doesn't blow up on an address violation) it does kind of
  emphasize the nature of uninitialized values.
   ---- before (an uninitialzed array2) ----
   array2[0]=29590344     |        0x400b0d
   array2[1]=1978349896   |        0x400b11
   array2[2]=-998029078   |        0x400b15
   array2[3]=1096637192   |        0x400b19
   array2[4]=1096630620   |        0x400b1d
   array2[5]=-1017167522  |        0x400b21
   array2[6]=254699152    |        0x400b25

Hello from square_array_values(), size=7
array= 0x7ffc36ef7da0, &(array)= 0x7ffc36ef7d58
   Note that the Value of our array param here is the same as main()'s array1, above.
   But the Address of our array param here, &(array) is Different than the main()'s &(array1), above.
before malloc, result=          (nil), &(result)= 0x7ffc36ef7d70
 after malloc, result=      0x2082010, &(result)= 0x7ffc36ef7d70
   Note that none of the values above for main()'s array2 match what we have
   here for square_array_value()'s variable result.
   They value of main()'s array2 Will match our value of result after we return (see below).
So, let's square some values...
   array[0]=1   | result[0]=1
   array[1]=2   | result[1]=4
   array[2]=3   | result[2]=9
   array[3]=4   | result[3]=16
   array[4]=5   | result[4]=25
   array[5]=6   | result[5]=36
   array[6]=7   | result[6]=49
Goodbye from square_array_values(), returning result=0x2082010
back in main().
array1= 0x7ffc36ef7da0, &(array)= 0x7ffc36ef7da0
   Note we have no differences from 'before.array1', above.
   All of array1's values and addresses are the same.
   ---- after ----
   array1[0]=1            |  0x7ffc36ef7da0
   array1[1]=2            |  0x7ffc36ef7da4
   array1[2]=3            |  0x7ffc36ef7da8
   array1[3]=4            |  0x7ffc36ef7dac
   array1[4]=5            |  0x7ffc36ef7db0
   array1[5]=6            |  0x7ffc36ef7db4
   array1[6]=7            |  0x7ffc36ef7db8
array2=      0x2082010, &(array2)= 0x7ffc36ef7d98
   array2, however, is significantly different from 'before.array2', above.
   array2 is now pointing to nicely initialized memory - thank you, square_array_values().
   ---- after (now array2 is initialized) ----
   array2[0]=1            |       0x2082010
   array2[1]=4            |       0x2082014
   array2[2]=9            |       0x2082018
   array2[3]=16           |       0x208201c
   array2[4]=25           |       0x2082020
   array2[5]=36           |       0x2082024
   array2[6]=49           |       0x2082028
main(): done.
$ 

foo.c的

我在你的原始代码中填充了一些相当疯狂的printf(),以及一个用于转储给定数组的辅助函数。通常情况下,我不会在自己的开发中走得那么远,但我希望您能够更容易地“想象”程序在运行时的内存位置。

#include <stdio.h>
#include <malloc.h>

int *square_array_values(int *array, int size); /* modified return type */
void dump_array( char *msg, char *label, int *array, int size );

int main() {
    /* typo? double 4's ? */
    /* ORIGINAL: int array1[] = {1, 2, 3, 4, 4, 5, 6}; */
    int array1[] = {1, 2, 3, 4, 5, 6, 7};
    int size = sizeof(array1)/sizeof(int);
    int *array2; /* we can let square_array_values() assign the result array */
    /* Or you could declare another array up here and pass that in */

    printf("hello from main(), size=%d\n", size );
    printf("array1=%15p, &(array1)=%15p\n", array1, &array1 );
    printf("  Note that &(array1[0]) equals both the value of array1 and &(array1), above.\n");
    printf("  Also, each subsequent address of array1's elements is sizeof(int) = %ld more\n", sizeof(int) );
    printf("  than the previous element, e.g. &(array[N]) = &(array[N-1]) + %ld)\n", sizeof(int) );
    dump_array( "before, array1", "array1", array1, size );
    printf("array2=%15p, &(array2)=%15p\n", array2, &array2 );
    printf("   We haven't allocated array2 yet, so no contents to print out.\n");
    printf("   In fact, we Really Shouldn't be printing what array2 'points' to at all,\n");
    printf("   but (when it doesn't blow up on an address violation) it does kind of\n");
    printf( "  emphasize the nature of uninitialized values.\n");
    dump_array( "before (an uninitialzed array2)", "array2", array2, size );


    /* original - try running it this way too...
     *     void square_array_values( &array1, size);
     */
    array2 = square_array_values(array1, size);
    printf("back in main().\n");

    printf("array1=%15p, &(array)=%15p\n", array1, &array1 );
    printf("   Note we have no differences from 'before.array1', above.\n");
    printf("   All of array1's values and addresses are the same.\n");
    dump_array( "after", "array1", array1, size );

    printf("array2=%15p, &(array2)=%15p\n", array2, &array2 );
    printf("   array2, however, is significantly different from 'before.array2', above.\n");
    printf("   array2 is now pointing to nicely initialized memory - thank you, square_array_values().\n");
    dump_array( "after (now array2 is initialized)", "array2", array2, size );

    free( array2 );
    printf("main(): done.\n");
}

int *square_array_values(int *array, int size) {
    int i;
    int *result;
    printf("\nHello from square_array_values(), size=%d\n", size );
    printf("array=%15p, &(array)=%15p\n", array, &array );
    printf("   Note that the Value of our array param here is the same as main()'s array1, above.\n");
    printf("   But the Address of our array param here, &(array) is Different than the main()'s &(array1), above.\n");
    printf("before malloc, result=%15p, &(result)=%15p\n", result, &result);
    result = malloc( sizeof(int) * size );
    printf(" after malloc, result=%15p, &(result)=%15p\n", result, &result);
    printf("   Note that none of the values above for main()'s array2 match what we have\n");
    printf("   here for square_array_value()'s variable result.\n");
    printf("   They value of main()'s array2 Will match our value of result after we return (see below).\n");
    printf("So, let's square some values...\n");
    for (i = 0; i < size; i++) {
        result[i] = array[i] * array[i];
        printf("   array[%d]=%d   | result[%d]=%d\n", i, array[i], i, result[i] );
    }
    printf("Goodbye from square_array_values(), returning result=%p\n", result);
    return result;
}

void dump_array( char *msg, char *label, int *array, int size ) {
   printf("   ---- %s ----\n", msg );
    for (int i = 0; i < size; i++) {
        printf("   %s[%d]=%-12d | %15p\n", label, i, array[i], &(array[i]) );
    }
}