Гарантия неравенства указателей на стандартные функции? - PullRequest
0 голосов
/ 16 октября 2018

Гарантирует ли язык C, что указатели на стандартные функции с разными именами должны сравниваться не одинаково?

За 6.5.9 Операторы равенства , ¶6,

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

Кажется, я помню, как видел интерпретацию, утверждающую, что псевдонимы (множественные идентификаторы для «одной и той же функции») допустимы для стандартных функций, каноническими кандидатами для такого обращения являются getc==fgetc и putc==fputc;однако, я не знаю, где я мог это увидеть, и скептически отношусь к этой концепции.

Есть ли официальное толкование или общепринятый аргумент за или против этой возможности?

Ответы [ 2 ]

0 голосов
/ 19 октября 2018

Ну, вы попадаете в подробность реализации .Стандарт определяет только поведение функций стандартной библиотеки.

Для getc спецификация говорит (подчеркните мое):

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

Таким образом, реализация может реализовать getc как макрос, но она также может реализовать его как псевдоним (простой указатель на func) для fgetc или как другую функцию с таким же поведением.Короче говоря, вы не можете полагаться на &getc == &fgetc как на истину или ложь.


Единственное, что требует стандарт, это то, что '& getc` должно быть определено в 7.1.4 § 1:

... разрешается брать адрес библиотечной функции, даже если он также определен как макрос ...

Это просто означает, что реализация должна иметьфункция с таким именем, но она может:

  • быть функцией fgets - ок &fgetc == &getc верно
  • использовать макрос - fgetc == &getc ложно
  • вызов функции fgets - &fgetc == &getc false
0 голосов
/ 19 октября 2018

Нет, я не верю, что есть какая-либо такая гарантия.

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

Из C17 7.1.4:

Любая функция, объявленная в заголовке, может быть дополнительно реализована как функционально-подобный макрос, определенный в заголовке, поэтому, если библиотечная функция объявлена ​​явнокогда его заголовок включен, один из методов, показанных ниже, может быть использован, чтобы гарантировать, что объявление не затронуто таким макросом.Любое макроопределение функции может быть подавлено локально, заключив имя функции в круглые скобки, потому что тогда за именем не следует левая скобка, которая указывает на расширение имени макрофункции.По той же синтаксической причине разрешается брать адрес библиотечной функции, даже если он также определен как макрос 189) .


189) Это означает, что реализация должна предоставлять фактическую функцию для каждой библиотечной функции, даже если она также предоставляет макрос для этой функции.

В тексте описывается, как пользователи могут #undef макросимя, если они хотят гарантировать, что они получают фактическую функцию.

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

Исходя из этого, я не верю, что есть какие-либо гарантии того, что разные функции имеют разные адреса.

В конкретном случае getc стандарт гласит (C17 7.21.7.5):

Функция getc эквивалентна fgetc, за исключением того, что если она реализована какмакрос, он может оценивать stream более одного раза, поэтому аргумент никогда не должен быть выражением с побочными эффектами.

Я бы сказал, что вполне вероятно, что реализация вызывает одну и ту же фактическую функцию для fgetc и getc, когда они реализованы как макросы.(Или что atoi против strtol вызывают ту же функцию и т. Д. И т. Д.).Реализации стандартной библиотеки, на которые я заглянул, похоже, не делают этого так, но я не думаю, что в стандарте есть что-то, что могло бы их остановить.


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

...