Неполные типы в возвращаемом типе и параметрах функции объявлены, но не определены

Является ли следующий код действительным C? (божественная стрела)

typedef struct none none;
none f(none, none);

Для ясности: идентификатор f никогда не появляется в единице перевода. снова и сама функция никогда не определена, даже в другом единица перевода.

Вы пробовали его скомпилировать? (Если скомпилировано - валидно, иначе - не валидно)

manish ma 11.12.2020 19:11

@sergeyrar Я не спрашиваю, принимают ли определенные компиляторы код как есть. Некоторые делают, некоторые нет. Я спрашиваю, действительно ли это с точки зрения стандарта. Обратите внимание на тег language-lawyer.

nebel 11.12.2020 19:13

Из любопытства, какие компиляторы это принимают и не принимают? Вы уверены, что все они намерены соответствовать одному и тому же стандарту? Я еще не нашел ни одного, кто не принимает это.

Nate Eldredge 11.12.2020 19:20

@NateEldredge gcc, clang и другие принимают код. cparser (git, а не на godbolt) не принимает его. Он жалуется на неполный тип параметра: cparser: «ошибка: анонимный параметр имеет неполный тип».

nebel 11.12.2020 19:36

Интересно: GCC 10,2.0, работающий на RHEL 7.4, принимает код даже с опциями gcc -pedantic -pedantic-errors -Wall -Werror -Wextra -std=c18 …. Если вы пытались использовать или реализовать функцию в исходном файле, то ошибка правильная — и GCC ее замечает. Я думаю, что есть основания утверждать, что cparser правильно, и GCC имеет недосмотр. Однако я не уверен, что соответствующая программа сможет обнаружить проблему — это не соответствующий код, если он не будет компилироваться в соответствующем компиляторе.

Jonathan Leffler 11.12.2020 19:51
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
5
124
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Стандарт C17 прямо говорит, что параметры могут иметь неполные типы:

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

Таким образом, cparser неправильно отклоняет код на этом основании.

Что касается типов возвращаемых значений, в любом случае нет четкого утверждения. cppreference говорит: «Тип возвращаемого значения функции [...] должен быть полным типом объекта, не являющимся массивом, или типом void», но я не могу найти соответствующее требование в стандарте. В стандарте 6.9.1 (3) в разделе «Определения функций» говорится, что «тип возвращаемого значения функции должен быть void или полным типом объекта, отличным от типа массива», но я прочитал, что это относится только к определениям. Аналогично, 6.5.2.2(1) требует, чтобы вызываемая функция имела полный тип возвращаемого значения или void.

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

«[...] 6.9.1 (3) [...] но я прочитал, что это относится только к определениям». Я тоже так читал, но тогда валидность кода зависит от другого неизвестного для меня: нужно ли объявление функции в конечном определении (возможно, в другой TU) или нет?

nebel 11.12.2020 20:09

@nebel: я думаю, что нет. Функция f объявлена ​​с внешней связью, а в 6.9(5) говорится: «Если идентификатор, объявленный с внешней связью, используется в выражении (кроме как часть операнда оператора sizeof или _Alignof, результатом которого является целочисленная константа), где-то во всей программе должно быть ровно одно внешнее определение идентификатора, иначе их должно быть не более одного». Здесь мы находимся в случае «иначе», поэтому разрешено нулевое определение.

Nate Eldredge 11.12.2020 20:20

Другие вопросы по теме