C/C++

В каком языке, в Си или в C++, будет работать определённая функция внутри функции?

#include<stdio.h>
int main()
{
float infunction(float n)
{
float ininfunction(int n)
{
return n*1.5;
}
return n*n/3+ininfunction(n);
}
printf("\n infunction=5*5/3+5*1.5 = %.2f\n\n",infunction(5));
return 0;
}
gcc такое понимает: Nested functions are supported as an extension in GNU C, but are not supported by GNU C++
https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html
ДШ
Денис Шапошников
9 861
Лучший ответ
В компиляторе, придерживающемся стандартов, именно такой код работать на будет.

Ни в стандарте C, ни в стандарте C++ вложенных функций в таком виде не существует. В C++ есть лямбды, но они имеют другой синтаксис.

Подключение <stdio.h> показывает, что это С-код. На C++ было бы <cstdio>.
Вложенные функции являются нестандартным расширением языка C в компиляторе GCC.
Так что, да - GCC этот код откомпилирует.
Ayxan Hesenov
Ayxan Hesenov
65 822
Алексей Саловаров Первый скрин с Кланга на Android
Второй скрин с MinGW на Windows 10,
На GCC и так работает, скрин не нужен.
Не работает только в C++ нигде, ни на одной платформе.
только на GCC. замещение определения функции внутри скоупа поддерживается только этим компилятором.
замещение не являются частью языка С и является не стандартной конструкцией.
C не поддерживает перегрузку функций хотя бы из-за того что в C нет манглига сигнатур для определения входящих типов аргументов. более того у C нет и не будет ABI это полностью ассемблированный язык программирования где программист всегда должен понимать как будет выглядеть его C код на ассемблере.
Приведённый пример содержит критическую ошибку как для языка C так и для когенерации. При замещении стандартного соглашения вызова с __cdecl на __stdcall обязаность отчищать стек после аргументов берет на себя вызываемый символ. если символ сгенерирован с 1 аргументом значит со стека будет снят 1 аргумент, соотвественно при вызове функции с соглашением __stdcall которой передали 3 аргумента а не 1 произойдет разбалансировка стека после возврата управления из функции.
Более того при JIT компиляции где адрес на функцию есть номер интерфейса вызываемого объекта произойдет ошибка приведения сигнатуры в любом случаее __cdecl или __fastcall.
Что касается последнего вопроса на ответ @Artem Basov то в GCC разрешено замещять декларации символов внутри скоупа функций. но это не перегрузка а замещение, и при подстановке аргумента из первостепенного декларирования произойдет ошибка.

Евгений Высочин, Перегрузка функции != загрузке адреса функции. перегрузка это сопоставление аргументов с сигнатурой функции.

void f(int);
void f(void*);

int main()
{
f(0);
f((void*)0);
return 0;
}

### -->>asm

define dso_local i32 @main() local_unnamed_addr #0! dbg! 9 {
tail call void @_Z1fi(i32 0), !dbg! 14
tail call void @_Z1fPv(i8* null), !dbg! 15
ret i32 0, !dbg! 16
}

declare! dbg! 17 dso_local void @_Z1fi(i32) local_unnamed_addr #1

declare! dbg! 20 dso_local void @_Z1fPv(i8*) local_unnamed_addr #1

main: # @main
pushq %rax
xorl %edi, %edi
callq _Z1fi
xorl %edi, %edi
callq _Z1fPv
xorl %eax, %eax
popq %rcx
retq
Алексей Саловаров Твой фрагмент С-кода это:

main:
push rbp
mov rbp, rsp
mov edi, 0
call f(int)
mov edi, 0
call f(void*)
mov eax, 0
pop rbp
ret
Алексей Саловаров мой код это main:
main:
push rbp
mov rbp, rsp
sub rsp, 16
lea rax, [rbp+16]
mov QWORD PTR [rbp-8], rax
lea rax, [rbp-8]
mov r10, rax
movss xmm0, DWORD PTR .LC2[rip]
call infunction.0
pxor xmm1, xmm1
cvtss2sd xmm1, xmm0
movq rax, xmm1
movq xmm0, rax
mov edi, OFFSET FLAT:.LC3
mov eax, 1
call printf
mov eax, 0
leave
ret
.LC0:
.long 0
.long 1073217536
.LC1:
.long 1077936128
.LC2:
.long 1084227584
Алексей Саловаров дальше, мой ininfunction.1:
ininfunction.1:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov QWORD PTR [rbp-16], r10
pxor xmm1, xmm1
cvtsi2sd xmm1, DWORD PTR [rbp-4]
movsd xmm0, QWORD PTR .LC0[rip]
mulsd xmm0, xmm1
cvtsd2ss xmm0, xmm0
pop rbp
ret
Алексей Саловаров дальше, мой infunction.0:
push rbp
mov rbp, rsp
sub rsp, 32
movss DWORD PTR [rbp-20], xmm0
mov QWORD PTR [rbp-32], r10
lea rax, [rbp+16]
mov QWORD PTR [rbp-8], rax
movss xmm0, DWORD PTR [rbp-20]
mulss xmm0, xmm0
movss xmm1, DWORD PTR .LC1[rip]
divss xmm0, xmm1
movss DWORD PTR [rbp-24], xmm0
movss xmm0, DWORD PTR [rbp-20]
cvttss2si eax, xmm0
lea rdx, [rbp-8]
mov r10, rdx
mov edi, eax
call ininfunction.1
addss xmm0, DWORD PTR [rbp-24]
leave
ret
.LC3:
.string "\n infunction=5*5/3+5*1.5 = %.2f\n\n"
очевидно же в с++ потомучто с++ это СИ доработанный он имеет всё что имел CИ
Алексей Саловаров Код вверху, попробуйте на своём компиляторе и дайте ответ со скрином ;)