Занимают ли функции пространство памяти?

void demo() { printf("demo"); } int main() { printf("%p",(void*)demo); return 0; } 

Вышеприведенный код печатает адрес функции demo .
Поэтому, если мы можем напечатать адрес функции, это означает, что эта функция присутствует в памяти и занимает некоторое место в ней.
Итак, сколько пространства занимает память?

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

Да, функции, которые вы пишете, скомпилированы в код, который хранится в памяти. (В случае интерпретируемого языка сам код хранится в памяти и выполняется интерпретатором.)

Итак, сколько пространства занимает память?

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

Вы можете сами убедиться, используя objdump -r -d :

 0000000000000000 : 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 4: bf 00 00 00 00 mov $0x0,%edi 5: R_X86_64_32 .rodata 9: b8 00 00 00 00 mov $0x0,%eax e: e8 00 00 00 00 callq 13  f: R_X86_64_PC32 printf-0x4 13: 5d pop %rbp 14: c3 retq 0000000000000015 
:

РЕДАКТИРОВАТЬ

Я взял ваш код и скомпилировал его (но не связал!). Используя objdump вы можете увидеть фактический способ, которым компилятор излагает код для запуска. В конце дня нет такой функции, как функция: для CPU это просто переход в какое-то место (что в этом листинге помечено). Таким образом, размер «функции» – это размер кода, который его содержит.


Кажется, есть некоторая путаница, что это как-то не «настоящий код». Вот что говорит GDB:

 Dump of assembler code for function demo: 0x000000000040052d <+0>: push %rbp 0x000000000040052e <+1>: mov %rsp,%rbp 0x0000000000400531 <+4>: mov $0x400614,%edi 0x0000000000400536 <+9>: mov $0x0,%eax 0x000000000040053b <+14>: callq 0x400410  0x0000000000400540 <+19>: pop %rbp 0x0000000000400541 <+20>: retq 

Это точно такой же код, с точно таким же размером, исправленный компоновщиком для использования реальных адресов. gdb печатает смещения в десятичной objdump тогда как objdump использует более благоприятный гексагон. Как вы можете видеть, в обоих случаях размер составляет 21 байт.

Конечно, он занимает пространство в памяти, вся программа загружается в память после ее выполнения. Как правило, инструкции программы хранятся в младших байтах пространства памяти, называемом text section . Вы можете узнать больше об этом здесь: http://www.geeksforgeeks.org/memory-layout-of-c-program/

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

Стандарт не дает способа определить, сколько пространства занимает функция в памяти, как арифметика указателя, трюк, позволяющий вычислять размеры смежных областей памяти в памяти данных, не определен для указателей функций. Кроме того, ISO C запрещает преобразование указателя функции на тип указателя объекта, поэтому вы не можете обойти это ограничение, наведя указатель на функцию, например, char* .

 printf("%p",demo); 

Вышеприведенный код печатает адрес функции demo() .

Это неопределенное поведение: %p ожидает void* , в то время как вы передаете ему void (*)() . Вы должны увидеть предупреждение компилятора, указав, что то, что вы делаете, недействительно ( демо ).

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

Функции скомпилированы в машинный код, который будет работать только на определенной ISA (x86, возможно, ARM, если он будет работать на вашем телефоне и т. Д.). Поскольку для разных процессоров может потребоваться больше или меньше инструкций для запуска той же функции, а длина инструкций также может меняться, нет способа узнать заранее, насколько велика функция, пока вы ее не скомпилируете.

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

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

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