2016-05-07 4 views
-2

Рассмотрим файл заголовка foo.h, который содержит:Почему существование типа возврата предотвращает необходимость прямого объявления для параметра?

struct wl_display; 

struct wl_array * bar(struct wl_display *display); 

и файл реализации foo.c, который содержит полное определение wl_display и реализацию bar:

struct wl_display { 
    int baz; 
}; 

struct wl_array * bar(struct wl_display *display) { 
    // ... 
} 

Если я удалю форвардную декларацию struct wl_display, от foo.h, gcc Компилятор:

  1. Испустите предупреждение о том, что возникновение struct wl_display *display в списке параметров находится в блоке области действия (предупреждение: «структура wl_display» объявлена ​​внутри списка параметров и предупреждение: сфера его применения только это определение или объявление, которое, вероятно, не то, что вы хотите).
  2. Исправить ошибку: конфликтующие типы для «бара» бар (структура wl_display * дисплей).

Однако, если я затем добавить функцию, которая использует STRUCT wl_display * в качестве возвращаемого типа, так что foo.h содержит:

// struct wl_display; 

struct wl_display * foo(void); 

struct wl_array * bar(struct wl_display *display); 

Все компилируется.

Почему использование struct wl_display* в качестве типа возврата устраняет необходимость в прямом объявлении? Что такое «конфликт», который вызывает ошибку № 2 выше, поскольку тип параметра является только указателем, а сигнатуры функций идентичны?

+0

Возможно, потому что объявление функции находится в области файлов? Список параметров является локальным для функции? –

+1

'struct wl_display;' определяет * неполный тип *. который здесь используется как * непрозрачный тип *. – wildplasser

ответ

1

Любое использование struct wl_display в области содержимого является прямым объявлением типа. Поэтому, если компилятор видит это первым, использование в списке параметров относится к этому типу. Если объявление в списке отображается первым, это объявляет тип, действительный только для списка, и нигде больше.

+0

@ybakos: Пожалуйста, начните с разницы между использованием самой 'struct' (где вам нужен размер -> полный тип) или указателем, где нет, если вы не разыщите этот указатель. – Olaf

+0

@ybakos: Это не так. Это точно здесь. Не замечая, что это хороший показатель, вам нужно больше узнать об этом предмете. – Olaf

+0

@Olaf Пожалуйста, просветите меня или отправьте ответ. Я понимаю разницу между использованием неполного типа и возможностью свободно ссылаться на тип указателя без необходимости форвардного объявления. Я спрашиваю, почему _в каком-либо явном прямом объявлении _or_ использование идентификатора того же типа, что и тип возвращаемого указателя, делает компилятор счастливым, когда снова появляется указатель на неполный тип в списке параметров последующей функции. Другими словами, как используется тип возвращаемого типа 'struct wl_display *', действует так же, как явное форвардное объявление' struct wl_display; '. – ybakos

1

Первая ссылка на struct wl_display представляет собой декларацию, хотя и неполную. В случае возвращаемого типа функции это объявление верхнего уровня. Но внутри списка аргументов это не так. Вместо этого, когда объявлено внутри списка аргументов, декларация ограничена внутри функции и выходит за рамки после определения функции.

+0

Но тип возврата не является форвардным заявлением, не так ли? – ybakos

+1

Тип возврата может включать объявление структуры, объединения или перечисления или определение, так же, как объявление переменной. –

+0

Я не спрашиваю, каковы действительные типы возвращаемых данных, скорее, я спрашиваю, как тип возвращаемого значения, являющийся структурой, интерпретируется как декларация пересылки, когда он не является автономным форвардным объявлением. – ybakos