Передача массива по ссылке вызывает предупреждения компилятора — Как здесь правильно использовать указатель-арифметику?

#arrays #c #pointers #pass-by-reference #pointer-arithmetic

#массивы #c #указатели #передача по ссылке #указатель-арифметика

Вопрос:

 void foo(int **arr)
{
    **arr = 5;     // works fine, no warnings and myArray[0] is 5 after call.
    *(arr 5) = 5;  //warning - assignment makes pointer from integer without a cast - why?
    *(arr)[5] = 5; //No warnig but programm would crash
}   

int main()
{

    int *myArray = (int*)calloc(10,sizeof(int));

    foo(amp;myArray); //no warning but myArray[5] would be still 0
    foo(myArray);  //warning - passing argument 1 of 'foo' from incompatible pointer type (but works fine)

    printf("%d",myArray[5]);

    return 0;
}
  

Как правильно передать массив в мою функцию и получить доступ к myArray[5] без каких-либо предупреждений?

Ответ №1:

Как написано, правильный способ индексирования в arr будет

 (*arr)[5] = 5;
  

Поскольку arr это указатель на указатель на ваш массив, вы не хотите индексировать в arr , вы хотите индексировать в то, на что arr указывает. Вам нужно явно сгруппировать * с arr , поскольку постфиксные операторы типа [] имеют более высокий приоритет, чем унарные * .

Сказав это, единственная причина передать указатель на myArray — это если вы ожидаете изменить значение myArray самого себя, например, с помощью вызова realloc . Если это не является намерением, тогда лучше написать функцию, как показали Антти и Питер.

Ответ №2:

Поскольку foo принимает указатель на указатель на целое число, вызов foo(amp;myArray) здесь правильный. Но вам вообще не нужно этого делать. Просто передайте myArray и foo вместо этого возьмите указатель на int:

 void foo(int *arr)
{
   arr[5] = 5;
}   

int main()
{
    int *myArray = calloc(10, sizeof(int)); // no need to cast here unless compiling with a C   compiler

    foo(myArray);

    printf("%d",  myArray[5]); // prints 5

    return 0;
}
  

Я знаю, что указатели могут сбивать с толку, но, похоже, здесь очень фундаментальное недоразумение, поэтому я рекомендую внимательно прочитать раздел указателей любого хорошего учебника по C еще раз.

Комментарии:

1. Спасибо. Я работал над своими знаниями о «указателе на указатель» и спросил себя, как работать с массивом в этом контексте. На слайде лекции было написано, что указатель на указатель используется для вызова по ссылке с массивами — поэтому я попробовал это, и это меня смутило. Спасибо, что помогли мне.

Ответ №3:

Вот так:

 #include <stdio.h>
#include <stdlib.h>

void foo(int *arr) {
    arr[5] = 5;
}   

int main(void) {
    int *myArray = calloc(10, sizeof(int));    
    foo(myArray);    
    printf("%d", myArray[5]);
}
  

Вам нужно передать указатель по ссылке только в том случае, если вы хотите изменить значение исходного объекта указателя (т. Е. Если вы хотите, чтобы указатель, сохраненный в, myArray указывал на другой выделенный блок памяти после вызова foo ).