你能在char数组中表示函数吗?

时间:2016-12-16 02:05:34

标签: c++ arrays function

我了解到功能和数据没有内在差异。是否可以初始化char数组,并将char指针强制转换为函数指针,并将其用作函数。我没有足够的知识来实现​​它,因为我不知道编译器用来表示内存块中的函数指令的方式。但我相信这个网站上有人有足够的专业知识来实现​​它。 :)

char* a = "blahbleeblue";//gibberish to other people
auto func = reinterpret_cast<void(*)()> a;
func();//due to careful planning, do what ever you ask

3 个答案:

答案 0 :(得分:1)

“我了解到功能和数据没有内在差异。”

在某些语言中,通常是解释的语言,就是这种情况。像javascript,lisp等。

在c中情况并非如此。数据和代码是完全不同的东西(我知道它们是存储在内存中的位,但并不是真正相关的)并且大多数操作系统都会竭尽全力阻止你做你正在做的事情混合它们(它看起来像bug或者黑客)。

当您执行CS500级课程时,您可能会发现代码在运行时重写代码的位置,有效地将其代码视为数据,但这种情况很少见

答案 1 :(得分:0)

也许这是一个X-Y问题 我假设你想要根据一些字符串执行一个函数。

功能指针和地图
此技术仅在函数签名相同时才有效:

// Define a synonym for a function pointer that returns nothing  
// and has a single integer argument.
typedef void (*Function_Pointer(int argument));

// Some declarations:  
void Process_Apple(int a);
void Process_Pineapple(int b);
void Process_Carrot(int c);

// Initialize the map
typedef std::map<std::string, Function_Pointer> Function_Dictionary;
Function_Dictionary func_table;
func_table["apple"] = Process_Apple;
func_table["pineapple"] = Process_Pineapple;
func_table["carrot"] = Process_Carrot;

// You can use 'find' to find the associated function
Function_Dictionary::iterator iter;
std::string function_name = "apple";
iter = func_table.find(function_name);
if (iter != func_table.end())
{
  Function_Ptr f = iter->second;
  // Execute the function
  f(27);
}

表格查询
您还可以创建一个表并使用查找。

struct Func_Assoc
{
  char * name;
  Function_Ptr f;
};
Func_Association lookup_table[] =
{
  {"apple", Process_Apple},
  {"pineapple", Process_Pineapple},
  //...
};
static const table_size =
  sizeof(lookup_table) / sizeof(lookup_table[0]);

lookup_table中搜索名称,然后使用相关的函数指针。这个方案的一个很好的优点是数据是常量和只读的,并且可以由程序访问而无需任何运行时初始化。

参见:工厂设计模式,反射

答案 2 :(得分:-1)

确实可以做到。这是一个例子:

#include <iostream>
#include <functional>

void say_hello(void) {
    std::cout << "Hello world\n";
}

using fptr = std::function<void(void)>; 

int main() {
    char *cptr = reinterpret_cast<char *>(&say_hello);
    fptr func = reinterpret_cast<void (*)(void)>(cptr);

    func();
    return 0;
}

输出:

Hello world

http://ideone.com/uFUKcw

如果你想建立自己的字符串,它会以某种方式评估为函数指针,这是不可能的,因为

  1. 指针必须指向用户定义的常量,即您决定使用的字符串。

  2. 这个常量必须存在于某个内存地址,该地址与指针指向的内存地址相同...你能看到问题吗?

  3. 现在,如果您还决定此指针必须以某种方式评估函数,那么一个选项立即无法实现,因为

    指针不能(不应该)同时指向两个不同的东西。如果指针指向静态字符串(请参阅上面的第二点),则它也不应同时指向函数地址。 你唯一的另一个选择需要另外两件事

    1. 你的编程水平很低(内核很多)
    2. 您确切知道数据段的确切位置
    3. 从这里开始是非常理论化的

      此时,我甚至不确定这会有多好用,因为我只看到了OS代码远程关闭的东西。当操作系统启动时,它需要设置一块内存以初始化一些内容(确定可用的总内存,设置页面表,启动文件系统等)。它分配的这个块有一个已知的物理地址,使用它,启动过程的初始化代码可以将函数放在它选择的位置

      现在,假设你的函数驻留在内存地址0x1EETC0DE,你可以使用普通的无符号整数来保存这个值。

      unsigned secret_weapon = 0x1EETC0DE;
      

      当时机成熟时,您可以简单地创建此整数并将其值转换为函数指针,并且......您可以从此处决定。