C 的基本原理不允许函数阵列

The rationale of C++ disallowing array of functions?

本文关键字:不允许 函数 阵列      更新时间:2023-10-16

C 不允许定义功能类型的基本原理(技术或概念)是什么?例如

using fn_t = int(int);
fn_t ary[2]; // ERROR (ref: ISO/IEC-14882 [dcl.array])

给定两个随机函数,我刚刚构成:

int a( int x, int y )
{
  return x * y;
}
int b( int x, int y )
{
  int result = 0;
  for (int xi = 1; xi <= x; xi++)
  for (int yi = y; yi >  0; yi--)
    result += xi * xi;
  return result;
}

您如何建议我将它们放在数组中?

我想我可以编译它们,然后只有一个max(sizeof(a的bytecode),sizeof(b's bytecode))的数组。但是现在我还有一些其他注意事项:

  • 这个数组在哪里?
    一些处理器可以从内存中的任何地方运行代码。有些不能。

  • 该代码的安全属性如何?

  • 搬迁注意事项呢?

  • 我如何称呼此功能?
    我可以使用处理器通常的通话惯例吗?还是这需要额外的幕后魔术?

  • 当我想要一个指针到数组时会发生什么?
    如果我移动阵列然后调用指针?

  • 会发生什么?
  • 例外和其他异常信号注意事项呢?

这只是冰山一角。做这种事情有很多技术因素。

导致主要考虑因素:

这将给函数的指针带来什么优势?

使用指向功能的指针,我可以做我本来想做的所有事情:

int (*fs)(int,int)[] = { a, b };
int x = fs[0]( 10, 10 );
int y = fs[1]( 10, 10 );

该语言设计了几个目标 - 最重要的两个是 Simplicity 灵活性

做您将要减少每个人的简单性和灵活性:编译器作家,编译器本身,运行时管理,速度,安全等等。

编辑: TL; DR 因为它与指针或对功能的引用没有任何优势,但有很多缺点。

C 不允许定义功能类型的基本原理(技术或概念)?

什么是功能?这只是地址上的一些代码。从概念上讲,这是一个单身人士,因为没有合理的方法可以复制一个或在堆上分配一个。你为什么?它已经存在。它有一个名称,该名称得出一个功能指针 - 代码的地址。

有一个"函数对象"的概念,它更等同于python或javaScript等高级语言的"第一类函数"。

但在引擎盖下,它被建模为包含代码地址(功能指针)和某些状态的结构。

有几种创建功能数组的方法:(此代码为C 14)

#include <functional>
#include <iostream>
int a(int i) {
    std::cout << "called a with " << i << std::endl;
    return i;
} 
int b(int i) {
    std::cout << "called b with " << i << std::endl;
    return i + 1;
} 
int c(int i) {
    std::cout << "called c with " << i << std::endl;
    return i + 2;
} 
int main()
{
    // make life easier by creating a typedef
    using raw_fptr = int (*)(int);
    // an array of function pointers
    raw_fptr raw_ptrs[] =
    {
        a, b, c
    };
    // a typedef of a std::function object
    using fobject = std::function<int(int)>;
    // an array of function objects
    fobject fobjects [] = {
        &a,                     // can capture a function pointer
        [](int i) -> int {      // or a lambda
            return b(i);
        },
        std::bind(&c, std::placeholders::_1) // or a binder
    };
    for (auto&& f : raw_ptrs)
        f(0);
    for (auto&& f : fobjects)
        f(1);
}