2016-06-06 2 views
5

Вот что это written в качестве обоснования для добавления звезды синтаксиса фантазии * для объявления типов массивов внутри функциональных прототипов - только для уточнения, прежде чем попасть в вопрос:Зачем использовать «[*]» вместо «[]» в прототипе функции?

Функция прототип может иметь параметры, которые имеют переменные длина типов массивов (§6.7.5.2) с использованием специального синтаксиса, как в int minimum(int,int [*][*]); Это согласуется с другими прототипами C, где необязательно указать имя .

Но я абсолютно уверен, что мы можем иметь тот же эффект, просто используя только обычные массивы неопределенного размера, как это (здесь переписывание примера функции с именем minimum приведенных выше в цитате с тем, что я считаю, именно та же функция) (для использования size_t вместо int в качестве первого параметра, который не является то, что важно в случае, за исключением):

#include <stdio.h> 


int minimum(size_t, int (*)[]); 

int (main)() 
{ 
    size_t sz; 

    scanf("%zu", &sz); 

    int vla[sz]; 

    for(size_t i = 0; i < sz; ++i) 
     vla[i] = i; 

    minimum(sizeof(vla)/sizeof(*vla), &vla); 

    int a[] = { 5, 4, 3, 2, 1, 0 }; 

    minimum(sizeof(a)/sizeof(*a), &a); 
} 


int minimum(size_t a, int (*b)[a]) 
{ 
    for(size_t i = 0; i < sizeof(*b)/sizeof(**b); ++i) 
     printf("%d ", (*b)[i]); 

    return printf("\n"); 
} 

Потому что я уверен, что там было какое-то место в стандарте о том, что 2 массивы совместимы, только если их размер равен и не имеет значения, если они являются переменными или не.

Моя точка зрения также подтверждается тем фактом, что определение minimum не будет жаловаться на «конфликтующие типы», как если бы некоторые из его параметров имели несовместимые типы (что, я думаю, не так, массивы имеют размер, который не указан во время компиляции - я ссылаюсь на второй параметр minimum).

OK кроме того - не могли бы вы указать мне 1 единый прецедент для [*], который нельзя заменить обычными массивами неуказанного размера?

Вышеприведенный код компилируется без каких-либо предупреждений с использованием как clang, так и gcc. Он также дает ожидаемый результат.

Для тех, кто не знает C (или любого, кто считает, что он это знает) - параметр функции массива типов неявно преобразуется в «указатель на его тип элементов». Так что это:

int minimum(int,int [*][*]); 

получает устанавливают:

int minimum(int,int (*)[*]); 

И тогда я, утверждая, что это может быть также записана как:

int minimum(int,int (*)[]); 

без каких-либо последствий и с таким же поведением как 2 формы выше. Таким образом, форма [*] устарела.

+4

'int (*) []' не является VLA. Какую ошибку компилятора вы получаете? Вы пытались хотя бы скомпилировать? Какова ваша позиция? Похоже на начало обсуждения. Это не дискуссионный форум. – Olaf

+2

@Olaf Я прошу использовать прецедент, где синтаксис звездного массива для прототипов функций не может быть заменен обычным массивом с неопределенным размером. И да 'int (*) []' не является VLA, но в чем ваш смысл? – AnArrayOfFunctions

+0

Нет синтаксиса звездного массива! Указатель не является массивом и наоборот. Изучите различия, есть достаточно вопросов об этих основах. – Olaf

ответ

6

OK кроме того - вы можете указать мне 1 одноразового использования случая для [*], который не может быть заменен с использованием обычных массивов неопределенного размера?

Это будет случай, когда вы передаете Трехмерные VLA массив:

int minimum(size_t, int [*][*][*]); 

Это можно записать в виде:

int minimum(size_t, int (*)[*][*]); 

или даже используя массив неопределенного размера:

int minimum(size_t, int (*)[][*]); 

Но у вас нет возможности пропустить ни обойти последний показатель, поэтому он должен оставаться [*] в таком объявлении.

+1

'Но вы не имеют возможности опуститься вокруг последнего индекса, поэтому он должен оставаться как [*] в таком объявлении. «Можете ли вы пояснить, что вы подразумеваете под этим? Грамматика достаточно просто, Я не могу сказать, что вы имеете в виду. – callyalater

+0

@callyalater: Отредактировано, надеюсь, теперь это лучше. –

+0

Гораздо лучше. Спасибо. Теперь это имеет гораздо больший смысл. – callyalater

6

[] может использоваться только как самый левый «спецификатор размеров» многомерного массива, тогда как [*] можно использовать в любом месте.

В декларациях параметров функции, крайний левый (только!) [...] доводят до (*) в любом случае, так что можно было бы использовать (*) в этом положении за счет какой-то ясности.

Можно опустить измерение в ближайшем к левому [...], оставив пустые скобки. Это приведет к тому, что тип элемента массива будет неполным.Это не имеет большого значения, поскольку можно завершить его близко к точке использования (например, в определении функции).

В следующем [...] требуется номер или *, внутри которого нельзя опустить. Эти заявления

int foo (int [*][*][*]); 
int foo (int (*)[*][*]); 
int foo (int (*)[ ][*]); 

все совместимы, но не один совместимый с ними, что не указывает третье измерение либо как * или номер. Если третье измерение действительно является переменной, * является единственным вариантом.

Таким образом, [*] необходим хотя бы для размеров 3 и выше.

Смежные вопросы