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
Вам нужно всего лишь использовать нотацию массива для многомерных массивов. (Вам не нужно указывать размер первого измерения).