Начало функции - указатель на функцию, вы уже это знаете.
Проблема в том, чтобы найти конец, но это можно сделать так:
#include <time.h>
int foo(void)
{
int i = 0;
++i + time(0); // time(0) is to prevent optimizer from just doing: return 1;
return i;
}
int main(int argc, char *argv[])
{
return (int)((long)main - (long)foo);
}
Это работает здесь, потому что программа имеет ТОЛЬКО ДВЕ функции, поэтому, если код переупорядочен (основной реализован до foo), то вы получите несущественный (отрицательный) расчет, сообщающий, что он не работал таким образом, но это это сработало бы, если вы переместите код foo () в main () - просто вычтите размер main (), полученный с начальным отрицательным ответом.
Если результат положительный, то он будет правильным - если заполнение не выполнено (да, некоторые компиляторы с радостью раздувают код либо для выравнивания, либо по другим, менее очевидным причинам).
Конечный (int) (long) приведен для переносимости между 32-битным и 64-битным кодом (указатели функций будут длиннее на 64-битной платформе).
Это очень портативный и должен работать достаточно хорошо.