如何在 C 中向现有代码添加新参数?

How to add new argument to existing code in C?

我正在处理一段调用底层 C 函数的现有 C++ 代码。目前的代码已经可以正常工作了,但我要做的是传入一些新的参数,并使用这些新的参数来修改一些行为。下面的代码演示了这个想法:

   // this is how the existing works look like without my changes:
   do_something_case1(int p1, double p2, struct1* p3, ...)
   {
       ... // do a lot of things

       // my work is to give client ability to override config1, config2
       // with their own structures. 
       // get_config1() and get_config2() are existing pre-defined 
       // configurations and are used extensively elsewhere. 

       ConfigStruct1 config1 = get_config1(...);
       ... // do a lot of things
       ConfigStruct2 config2 = get_config2(...);
       ... // do something
       foo(config1, config2, ...);
       ... // more code
   }

   do_something_case2(int p1, double p2, struct1* p3, ...)
   {
       // in a similar situation as do_something_case1
   }

   ... // more do_something_case3, do_something_case4 defined here

   // this function needs to take client overrides. 
   void do_something(int p1, double p2, struct1* p3, ...)
   {
       if(case1) 
       {
           do_something_case1(p1, p2, p3, ...);
       }
       else if(case2) 
       {
           do_something_case2(p1, p2, p3, ...);
       }
       else if(case3)
       {
           do_something_case3(p1, ...);
       }
       else if(...) // more if statements to come
       {
           ... // do something
       }
   }

我的工作是让客户能够使用自己的 ConfigStruct。在主要的 ConfigStruct1 中,ConfigStruct2 应该是输入而不是在函数中决定,这不会给客户端太多的自由来覆盖它们。然而,这些代码非常古老并且在系统中被广泛使用,我不想破坏任何现有的客户端代码。我绝对想利用这些 do_something_case() 函数中已经定义的所有其他复杂逻辑。如果这是 C++,我可以简单地添加一个采用默认值的新参数,

    // if it were C++, I could do:
    do_something_case1(int p1, double p2, struct1* p3, ..., 
                       ConfigStruct1* pConfig1=NULL, 
                       ConfigStruct2* pConfig2=NULL)
    {
        if(NULL == pConfig1)
        {
            // call get_config1(..)
        }
    }

或者使用函数重载。但由于 C 也不支持,我觉得我只能选择更少、更丑陋的选项。解决问题的一种方法是复制并粘贴所有这些功能,然后在新功能中进行外科手术式更改。这将使它更加丑陋。你对我的情况有什么建议吗?

非常感谢。

If this were C++, I could simply add a new argument that takes a default value

仅当您愿意并且能够重新编译所有使用此功能的东西。听起来这可能是个大麻烦,甚至可能不可行。 C++ 中的烟雾和镜子比实际的魔法要多得多。

[...] or use function overloading.

C++ 重载函数提前绑定——或者至少,在编译时选择任何特定调用中使用的特定重载签名。因此,简单地添加一个重载版本不足以让现有代码调用新版本。相反,您需要重新编译 everything。烟雾,镜子,没有魔法。

对于 C 语言的解决方案,更改 do_something_case() 函数的参数数量几乎是行不通的。这不仅需要您重新编译所有内容,还需要您修改每个调用。您可能可以利用 C 预处理器来自动执行其中的一些操作,但它仍然会很混乱。

看起来 get_config1()get_config2() 函数可能是可行的扩展点,但是,假设这些 return 指针 而不是问题中描述的实际结构。这假定客户端结构将符合预期的配置结构类型,并在末尾添加,这似乎无论如何都是 do_something_case() 调用的函数工作所必需的。您可以修改 get_config() 函数,但效果最好,或者可以设置一种机制,使客户端可以通过策略性地使用动态链接器来提供它们自己的实现。