Почему спецификатор «static» генерирует внешнее определение для встроенной функции?

В стандарте C99 для встроенного спецификатора (6.7.4, параграф 6) говорится:

«Если все объявления области файла для функции в переводе unit включает встроенный спецификатор функции без extern, тогда определение в этой единице перевода является строковым определение. Встроенное определение не предоставляет внешнего определение функции и не запрещает внешнее определение в другой единице перевода"

Однако когда я компилирую следующий код в godbolt:

static inline int foo(int a) {
    a = 1;
    return a; }


int main(void){
    return foo(-1);
}

, результат включает внешнее определение (должно быть с внутренней связью):

foo:  ; an external definition with internal linkage
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], edi
        mov     DWORD PTR [rbp-4], 1
        mov     eax, DWORD PTR [rbp-4]
        pop     rbp
        ret
main:
        push    rbp
        mov     rbp, rsp
        mov     edi, -1
        call    foo
        pop     rbp
        ret

Я думаю, что определение функции foo() в исходном коде является встроенным определением, и поэтому результат сборки не должен содержать определение, как когда мы объявляем его с помощью необработанного встроенного кода, но кажется, что нет, почему?
Обратите внимание: если мы скомпилируем следующий код в godbolt:


inline int foo(int a) {
    a = 1;
    return a; }


int main(void){
    return foo(-1);
}

Результатом будет:

; Here foo() is omitted because inline definition
main:
        push    rbp
        mov     rbp, rsp
        mov     edi, -1
        call    foo
        pop     rbp
        ret

Почему foo появляется в первом, но не появляется во втором, когда все определения foo являются встроенными определениями?

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

Какие уровни оптимизации вы используете?

Jonathan Leffler 18.04.2024 07:14

Возможно, это актуально: stackoverflow.com/a/34938209/4386427

Support Ukraine 18.04.2024 07:40

Возможно это актуально: stackoverflow.com/a/3100516/4386427

Support Ukraine 18.04.2024 08:18
an external definition with internal linkage Откуда вы знаете его внешний вид?
KamilCuk 18.04.2024 09:06

Я использую уровень оптимизации O0. Вы можете просмотреть ссылку godbolt и увидеть примеры с флагами компилятора. Второй точно содержит неопределенную ссылку и это ожидаемый результат. В C99 утверждается, что встроенное определение не должно создавать внешнее определение, поэтому правильно не выводить определение foo. Я думаю, что foo в сборке внешний из-за этой страницы в cppref.

Faraway 18.04.2024 10:44

Я просмотрел страницу gnu в этом ответе, и это меня еще больше озадачило. Там написано, что «нестатическая встроенная функция всегда компилируется сама по себе обычным способом». Однако в моих примерах он не компилирует функцию foo. Позже прочитаю более внимательно.

Faraway 18.04.2024 10:48

Заявления в стандарте C о том, генерируется ли внешнее определение, касаются семантики C, то есть того, как программа будет вести себя, как видно из ее наблюдаемого поведения. Это не утверждения о том, какой язык ассемблера будет сгенерирован. Наличие определения с локальной меткой в ​​сборке не является свидетельством нарушения семантики C.

Eric Postpischil 18.04.2024 13:18

@ericpostpishil Боже мой, я не могу поверить, что не заметил предварительных заявлений. Спасибо за ваше терпение, чтобы проверить это. Возможно, позже я решу удалить этот вопрос. Кстати, ваше мнение о наблюдаемом поведении весьма проницательно.

Faraway 18.04.2024 16:22
Стоит ли изучать 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
8
100
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Предложения, которые вы цитируете, появляются после вступления «Для функции с внешней связью применяются следующие ограничения:». Хотя предложения, которые вы цитируете, не содержат ограничений, они устанавливают терминологические определения для ограничений. Я бы интерпретировал их исключительно как функцию с внешней связью. Они не применяются к функциям с внутренней связью.

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