Понадобилось тут мне запихнуть указатель на функцию (function pointer) в отладочный вывод через printf. В C сделать это явным образом нельзя, но есть хитрый способ.
Проблема заключается в том, что указатель на функцию нельзя интерпретировать как обычный указатель или что либо другое "обычное". Указатель на функцию нельзя привести к другому типу объекта, хранящегося в оперативной памяти.
Решение:
/*!
\file
\brief Function pointer printf example
\license Public Domain
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
void tfunc()
{
printf("Hello world! 1");
}
void tfunc2()
{
printf("Hello world! 2");
}
int tfunc3(int a)
{
return a+5;
}
void __print_fp(void(*func)())
{
struct
{
void(*func)();
} tmp;
memset(&tmp, 0, sizeof(tmp));
tmp.func=func;
for(uint8_t i=0; i<sizeof(tmp); ++i)
{
printf("%02x", ((uint8_t*)(&tmp))[i]);
}
printf("\n");
}
#define print_fp(__func_ptr_par) __print_fp((void(*)())__func_ptr_par)
int main()
{
print_fp(tfunc);
print_fp(tfunc2);
print_fp(tfunc3);
return 0;
}
Проблема заключается в том, что указатель на функцию нельзя интерпретировать как обычный указатель или что либо другое "обычное". Указатель на функцию нельзя привести к другому типу объекта, хранящегося в оперативной памяти.
Решение:
- указатель на функцию можно засунуть в структуру;
- Создаем структуру с одним полем типа указателя на структуру.
- Заполняем структуру нулями
- Засовываем значение указателя в экземпляр этой структуры.
- Приводим структуру к массиву байт.
- Побайтово печатаем содержимое структуры.
У этого метода есть опасный момент - структура может быть выравнена, если размер структуры окажется больше размера указателя на функцию, то это приведет к печати лишних байт. С этой проблемой я готов мириться, мне вывод указателей нужен для отладки, чтобы вручную их сравнивать, лишние знаки мне не мешают.
Вот реализация:
/*!
\file
\brief Function pointer printf example
\license Public Domain
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
void tfunc()
{
printf("Hello world! 1");
}
void tfunc2()
{
printf("Hello world! 2");
}
int tfunc3(int a)
{
return a+5;
}
void __print_fp(void(*func)())
{
struct
{
void(*func)();
} tmp;
memset(&tmp, 0, sizeof(tmp));
tmp.func=func;
for(uint8_t i=0; i<sizeof(tmp); ++i)
{
printf("%02x", ((uint8_t*)(&tmp))[i]);
}
printf("\n");
}
#define print_fp(__func_ptr_par) __print_fp((void(*)())__func_ptr_par)
int main()
{
print_fp(tfunc);
print_fp(tfunc2);
print_fp(tfunc3);
return 0;
}
Комментариев нет:
Отправить комментарий