简体   繁体   English

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

[英]How to pass an array of integers to a function as an argument and modify the content?

I am trying to modify an array of integers through a function, but the array maintains its original values. 我正在尝试通过函数修改整数数组,但该数组保持其原始值。 I tried to accesses its values to modify it: 我试图访问其值以对其进行修改:

This produces an error: 这会产生一个错误:

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

This example runs the program but the array will be modified: 此示例运行程序,但将修改数组:

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];
    }
}

For arrays, the array name itself is the base address of the array. 对于数组,数组名称本身就是数组的基地址。 So for your example, you just need to send that( array ) to the function. 因此,对于您的示例,您只需要将that( array )发送给函数。

As sending arrays to some function decays them to a pointer, it would work perfectly with your implementation of square_array_values() 由于将数组发送给某些函数会将其衰减为指针,因此与您实现square_array_values()完美配合

Change to 改成

square_array_values(array, size);

I don't always say this, but since I am in a good mood. 我并不总是这样说,但是因为我心情很好。

Always do 总是做

int main(void)

and not 并不是

int main()

int main() means that main can accept any number of arguments. int main()表示main可以接受任意数量的参数。

You should not pass the address of the array, tha array itself is converted to a pointer. 您不应该传递数组的地址,而是将数组本身转换为指针。 Just change this 只是改变这个

square_array_values(&array, size);

to

square_array_values(array, size);

without the address of & operator, with it the pointer you passed has type int (*)[] instead of int * which is what you need. 没有&运算符的地址,您传递的指针的类型为int (*)[]而不是您需要的int *

Also, you could enable compiler warnings and an incompatible type warning should be issued. 另外,您可以启用编译器警告,并且应该发出不兼容的类型警告。

Passing the address of the array as &array is incorrect, you should just pass the array directly, The compiler will automatically pass a pointer to its first element. 由于&array不正确地传递数组的地址,您应该直接传递该数组,编译器会自动将指针传递给它的第一个元素。 This is called decaying . 这称为衰减

You observe that the array remains unchanged, but think again: you print the contents of each array element before modifying it. 您观察到该数组保持不变,但请三思而后行: 修改每个数组元素之前,先打印它们的内容。 Change the code to this: 将代码更改为此:

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]);
    }
}

Follow these steps: 跟着这些步骤:

  • Recompile and verify that the array is indeed modified. 重新编译并验证数组是否确实被修改。
  • Then move the definition of square_array_values before main and compile again: you should get a warning about the type mismatch. 然后移动的定义square_array_values之前main和重新编译:你应该得到一个类型不匹配的警告。
  • Finally fix the calling site as square_array_values(array, size); 最后,将调用站点固定为square_array_values(array, size); , and return 0; ,并return 0; from main . main

This is late to the answer party - I hope it gives you some ideas about how to add prints to your code to help show what is going on. 答案晚了-我希望它能为您提供一些有关如何在代码中添加打印内容以帮助显示问题的想法。

Consider the output from the following program. 考虑以下程序的输出。 There are several ways you could approach this, this is just one possibility. 有几种方法可以解决此问题,这只是一种可能性。 All of the earlier answers are solid and should give you some good ideas. 前面所有的答案都是可靠的,应该会给您一些好的想法。

You're going to need to build up your mental model of how memory allocation works in C so you can predict what the compiler will do. 您将需要建立关于内存分配如何在C中工作的思维模型,以便可以预测编译器将执行的操作。 I find that printing out the values of variables AND their addresses is often helpful. 我发现打印出变量的值及其地址通常会很有帮助。 You would benefit from sketching a "memory map" with paper and pencil so you know which variables are referencing which storage. 您将受益于用纸和笔绘制“内存图”,因此您知道哪些变量引用了哪个存储。

Foo.c output 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 Foo.c

I stuffed a fairly crazy number of printf()s into your original code, and a helper function to dump out a given array. 我在原始代码中塞满了相当数量的printf(),并使用了一个辅助函数来转储给定的数组。 Normally I wouldn't go this far in my own development, but I wanted it to be easier for you to "imagine" what your program's memory locations look like at run time. 通常,我不会在自己的开发中走这么远的距离,但是我希望它可以使您更轻松地“想象”程序在运行时的内存位置。

#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]) );
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM