Почему fpos_t *псевдоним ФАЙЛА*?

В книге Modern C Йенс Густедт утверждает, что:

За исключением типов символов, псевдонимами могут быть только указатели одного и того же базового типа.

Но затем я нахожу это объявление fgetpos() в Приложении B стандарта C:

int fgetpos(FILE * restrict stream, fpos_t * restrict pos);

где тип fpos_t определяется как:

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

что вызывает вопрос:

Почему псевдоним fpos_t * может быть FILE *? Это потому, что fpos_t может быть typedef для FILE ? Если нет, то что оправдывает использование restrict здесь?

Они не могут использовать псевдонимы друг друга. Я думаю, что в объявлении используется restrict просто для того, чтобы предоставить компилятору как можно больше информации. Вероятно, это избыточно.

Barmar 05.03.2024 18:12

Большинство (?) квалификаторов restrict в прототипах стандартной библиотеки используются для указателей с разными базовыми типами, поэтому здесь нет ничего особенного.

Ian Abbott 05.03.2024 18:15

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

Caulder 05.03.2024 18:24

Если FILE ограничивает одного и того же участника fpos_t, то вызов fgetpos() с этими двумя нарушает из-за restrict.

chux - Reinstate Monica 05.03.2024 18:47
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
86
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Во-первых, restrict в объявлении функции, которое не является определением, не имеет никакого эффекта в семантике C. В C 2018 6.7.6.3 15 говорится, что квалификаторы параметров игнорируются при определении совместимости функций, а это означает, что функция может быть объявлена ​​с restrict в ее параметрах, но определена без restrict или наоборот. Таким образом, использование restrict в документации, описывающей процедуру, — это просто совет читателю.

Обычно FILE и fpos_t не являются псевдонимами друг друга. (И обратите внимание, что нас интересует объект, а не указатель. Правила псевдонимов в 6.5.7 касаются того, какие типы lvalue могут использоваться для доступа к объекту, а не указателей, которые могут использоваться [за исключением, конечно, рассмотрения фактического псевдоним указателя].) Однако вы могли бы (в том смысле, что это возможно, но не желательно) объявить объединение, которое содержит как FILE (если ваша реализация C определяет его как полный тип), так и fpos_t, поэтому вы передаете в правильно подготовленном объекте FILE и готовы пожертвовать им и заменить его на fpos_t в той же памяти. Вы также можете сделать это с динамически выделяемой памятью, поскольку запись нового типа (fpos_t) поверх старого типа (FILE) является разрешенной формой псевдонимов (при записи в динамически выделяемую память любой тип, который вы используете, является эффективным типом, что разрешено для псевдонимов). Итак, restrict в документации fgetpos советует вам не делать этого.

Если поставить restrict в документации, это означает, что передача одних и тех же указателей для обоих может вызвать UB, верно?

Barmar 05.03.2024 19:10

@Barmar: Можно подумать, и это должно быть намерение, но я не вижу, чтобы это было заявлено.

Eric Postpischil 05.03.2024 19:20

Возможно, это более четко указано в C23, чем в C17/18: 6.7.4.2.8-9 «Цена состоит в том, что программисту приходится проверять все эти вызовы, чтобы убедиться, что ни один из них не приводит к неопределенному поведению. Например, второй вызов f в g имеет неопределенное поведение, поскольку доступ к каждому из d[1]-d[49] осуществляется как через p, так и через q"

Ted Lyngmo 05.03.2024 20:55

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

Вызов функции-члена неполного типа компилируется в gcc и не компилируется в clang и msvc
Почему std::allocator<T>::allocate вызывает ::operator new?
Использование константных выражений в качестве параметра шаблона с использованием параметра функции: какой компилятор прав?
Соблюдают ли компиляторы C «формальное определение ограничения»?
Влияет ли шаблонный конструктор с вариациями на тривиальность типа?
Почему decltype(member) не является константой, а decltype((member)) предназначен для константного объекта и как это влияет на вызовы функций
Почему использование адреса первого элемента массива в качестве аргумента, не являющегося типом шаблона, возможно в С++ 17
Неоднозначная специализация шаблонов с понятиями и реальными типами: какой компилятор прав?
Может ли функция когда-либо возвращать значение, отличное от ее явных возвращаемых значений?
`sscanf` для `%%` не работает должным образом