C указатель указателя по сравнению с записью массива: при переходе к функции

Мой вопрос основан на следующем коде:

int myfunct(int ary[], int arysize)   
int myfunct2(int *ary, int arysize)

 int main(void){
   int numary[10];
   myfunct(numary, 10)
   myfunct2(numary, 10)
   return;
 }

int myfunct(int ary[], int arysize) {   
      //Whatever work is done

  }

int myfunct2(int *ary, int arysize) {
     // Whatever work is done

  }

Есть ли причина использовать одну из них над другой? Чтобы уточнить, когда речь идет о числовых массивах, есть ли какая-то причина, по которой нужно было бы использовать обозначение указателя по нотации массива. Если использовать нотацию указателя, то в пределах функции указатель будет использовать арифметику и т.д. И если вы используете нотацию [] массива, можно было бы работать с массивом, как обычно. Я новичок в программировании, и в настоящее время я не вижу никакой пользы от использования нотации указателя.

Мой точный вопрос: есть ли какая-нибудь причина передать числовой массив функции, используя нотацию указателя и, следовательно, используя манипуляции с указателями внутри функции.

Ответ 1

Между двумя обозначениями нет реальной функциональной разницы. В C, когда вы передаете переменную массива в функцию, она распадается на указатель независимо от нотации. Однако, на мой взгляд, предпочтительная нотация указателя. Проблема с обозначением [] в определениях функций заключается в том, что, на мой взгляд, она несколько вводит в заблуждение:

void foo(int array[])
{

}

Вездесущая ошибка среди начинающих программистов C состоит в том, чтобы предположить, что sizeof(array) даст вам количество элементов в массиве, умноженное на sizeof(int), как если бы array была переменной массива, объявленной в стеке. Но реальность такова, что array был разложен на указатель, несмотря на вводящую в заблуждение нотацию [], и поэтому sizeof(array) будет sizeof(int*). array - это действительно просто указатель на первый элемент или, возможно, указатель на одно целое, выделенное где угодно.

Например, мы могли бы назвать foo следующим образом:

int x = 10;
foo(&x);

В этом случае обозначение [] в определении foo является ошибочным.

Ответ 2

Когда вы объявляете параметр функции как массив, компилятор автоматически игнорирует размер массива (если есть) и преобразует его в указатель. То есть это объявление:

int foo(char p[123]);

эквивалентен 100%:

int foo(char *p);

На самом деле речь идет не о нотации, а о фактическом типе:

typedef char array_t[42];
int foo(array_t p);  // still the same function

Это не имеет никакого отношения к тому, как вы получаете доступ к p внутри функции. Кроме того, оператор [] не является "обозначением массива". [] - оператор указателя:

a[b]

эквивалентен 100%:

*(a + b)

Ответ 3

Эти объявления абсолютно идентичны. Чтобы процитировать стандарт:

Объявление параметра как "массив типа" должно быть скорректировано на "квалифицированный указатель на тип"

Стандартная часть C99 6.7.5.3, пункт 7

Ответ 4

В современном C, который имеет переменную длину массивов с C99, нотация массива предпочтительнее, если это массив, я думаю. Для одномерных массивов вы можете делать такие вещи, как

int myfunct(size_t size, int array[size]) {
  ... array[i] ..
}

и для двумерного

int myfunct(size_t size, int array[size][size]) {
  ... array[i][j] ..
}

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

Ответ 5

На мой взгляд, основная причина, по которой в прототипах функций предпочтение отдается указателю над записью пустого массива, заключается в том, что последнее не согласуется с определениями структуры:

struct person {
   char *first;
   char *last;
};

void setperson(struct person *p, char first[], char last[])
{
    p->first = first;
    p->last = last;
}

В структурах вам все равно придется использовать обозначение указателя, поскольку пустое обозначение массива допустимо только, по крайней мере, начиная с C99, для последнего члена, если вы хотите сделать его гибким элементом массива.

Ответ 6

Вам нужно всего лишь использовать нотацию массива для многомерных массивов. (Вам не нужно указывать размер первого измерения).