Проблема указателей на массивы в C - PullRequest
2 голосов
/ 01 июля 2011

У меня есть эта функция, которая принимает указатель массива (чтобы изменить его изнутри функции)

int func_test(char *arr[]){
    return 0;
}

int main(){
  char var[3];
  func_test(&var);

  return 0;
}

Когда я пытаюсь скомпилировать это, я получаю:

passing argument 1 of ‘func_test’ from incompatible pointer type

Почему эта проблема и как я передаю указатель на этот массив в этом случае?

Ответы [ 7 ]

5 голосов
/ 01 июля 2011

char * arr[] не является указателем на массив;это массив указателей.Объявления в C читаются сначала из идентификатора вправо, затем из идентификатора влево.Итак:

    char * arr[];
//         ^ arr is...
//            ^ an array of...
//       ^ pointers to...
//  ^ char
4 голосов
/ 01 июля 2011

Указатель на массив - type (*varname)[], в вашем случае - char (*arr)[].

2 голосов
/ 01 июля 2011

Вы передаете адрес указателя. Я думаю, что вы хотите это:

int func_test(char arr[]){
    arr[0] = 'a';//etc.
    return 0;
}

int main(){
  char var[3];
  func_test(var);

  return 0;
}
1 голос
/ 01 июля 2011

char var[3] - это массив, который содержит 3 символа, а не 3 указателя на символы - char *arr[] обозначает массив, который содержит указатели на символы.

Таким образом, вы можете пойти так:

char *var[3];
func_test(var);

Обратите внимание, что амперсанд не нужен, потому что идентификаторы массива автоматически распадаются на указатели соответствующего типа, в данном случае char **.

0 голосов
/ 01 июля 2011
Обработка массивов в

C поначалу немного сбивает с толку.

За исключением случаев, когда это операнд оператора sizeof или унарный & или когда строковый литерал используется для инициализации другого массивав объявлении выражение с типом «массив N-элементов из T» будет неявно преобразовано в тип «указатель на T», а его значением будет адрес первого элемента в массиве.

Предположим,следующее объявление:

int x[10];

Типом выражения x является "массив из 10 элементов типа int".Однако, когда это выражение появляется, скажем, как параметр функции:

foo(x);

, тип x неявно преобразуется («распадается») в тип «указатель на int».Таким образом, объявление foo должно быть

void foo(int *p);

foo получает int *, а не int [10].

Обратите внимание, что это преобразование также происходит для чего-то вроде

i = x[0];

Опять же, поскольку x не является операндом sizeof или &, его тип преобразуется из "10-элементный массив int "to" указатель на int ".Это работает, потому что подписка массива определена в терминах арифметики указателя;выражение a[n] эквивалентно *(a+n).

Итак, для вашего кода вы должны написать

int func_test(char *arr) { return (0); }

int main(void)
{
  char var[3];
  func_test(var); // no & operator
  return 0;
}

Постфиксные операторы, такие как [], имеют более высокий приоритет, чем унарные операторы, такие как *, поэтому объявление типа T *a[N] интерпретируетсякак T *(a[N]), который объявляет массив указателей на T. Чтобы объявить указатель на массив, вы должны использовать скобки для явной группировки оператора * с именем массива, например T (*a)[N].

Вот удобная таблица объявлений, выражений и типов массивов:

Declaration: T a[N];          // a is an N-element array of T

Expression     Type           Decays To
----------     ----           ---------
         a     T [N]          T *
        &a     T (*)[N]       
      a[i]     T
     &a[i]     T *

Declaration: T *a[N];         // a is an N-element array of pointer to T

Expression     Type           Decays To
----------     ----           ---------
         a     T *[N]         T **
        &a     T *(*)[N]     
      a[i]     T *
     *a[i]     T
     &a[i]     T *

Declaration: T (*a)[N]       // a is a pointer to an N-element array of T

Expression     Type           Decays To
----------     ----           ---------
         a     T (*)[N]
        &a     T (**)[N]     
        *a     T [N]          T *
   (*a)[i]     T
0 голосов
/ 01 июля 2011

Это массив указателей

char *arr[]

Это адрес указателя

&var

То есть вы передаете что-то отличное от того, что ожидает функция

0 голосов
/ 01 июля 2011

Это потому, что имя массива уже является указателем на него, поэтому используйте func_test(var).

& var будет иметь тип char **

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...