【问题标题】:Runtime conditional typedef in CC中的运行时条件typedef
【发布时间】:2023-03-21 02:33:02
【问题描述】:

我知道这个问题有一个 C++ 版本,但是我使用的是标准类型定义而不是模板。

我编写了一个适用于 16 位 wav 文件的程序。它通过将每个样本加载到一个短片中来做到这一点。然后程序对短路进行算术运算。

我现在正在修改程序,以便它可以同时使用 16 位和 32 位 wav。我希望做一个有条件的 typedef,即对 16 位使用 short,对 32 位使用 int。但是后来我意识到,如果编译器事先不知道变量的类型是什么,它可能不会编译代码。

所以我尝试测试出以下代码:

#include <stdio.h>

int
main()
{
  int i;
  scanf("%i", &i);

  typedef short test;

  if(i == 1)
    typedef short sample;
  else 
    typedef int sample;

  return 0;
}

并得到以下编译器错误:

dt.c: In function ‘main’:
dt.c:12:5: error: expected expression before ‘typedef’
dt.c:14:5: error: expected expression before ‘typedef’

这是否意味着 C 中的运行时条件 typedef 是不可能的?

[开放式问题:]如果没有,你们将如何处理这样的事情?

【问题讨论】:

  • 是的,运行时 typedef 是不可能的。编译器需要为sample s; 分配存储空间,因为它必须知道大小。
  • 考虑使用&lt;inttypes.h&gt;(和/或&lt;stdint.h&gt;)和uint16_tint32_t等。当然,这是来自C99,但即使是逆行编译器通常也提供这种工具(或者可以与标题一起提供)。

标签: c types typedef


【解决方案1】:

typedef 是编译器功能,不能在运行时应用。

【讨论】:

    【解决方案2】:

    程序中的所有类型必须在编译时已知。

    在 C++ 中,您可以使用模板为 shortint 编译代码;在 C 语言中,您可以使用宏(特别是 X 宏)来做到这一点。

    将您的计算代码放在一个单独的文件中,例如dt.tmpl.c,然后在dt.c写:

    #define sample int
    #include "dt.tmpl.c"
    
    #define sample short
    #include "dt.tmpl.c"
    

    然后您的dt.tmpl.c 代码可以使用sample 作为预处理器标记来命名类型并粘贴到函数名称中,例如:

    #define PASTE(name, type) name ## _ ## type
    #define FUNCTION_NAME(name, type) PASTE(name, type)
    
    sample FUNCTION_NAME(my_calculation, sample)(sample i) {
        return i * 2;
    }
    

    这将产生两个函数 int my_calculation_int(int i)short my_calculation_short(short i),然后您可以在其他地方使用它们。

    【讨论】:

    • 您只能粘贴到宏中,因此您必须将函数名称设置为参数化宏调用,例如FUNCTION_NAME(my_calculation, SAMPLESIZE),其中SAMPLESIZE 可能是wav16 或@987654335 @,而FUNCTION_NAME 宏调用另一个宏将参数粘贴到一个名称中。
    • 更接近。有关详细说明,请参阅C Preprocessor and Concatenation。我在之前的评论中提到,您需要让函数名称宏调用另一个来进行粘贴。即使您修改后的代码也会生成my_calculation_sample,无论sample 被定义为什么。
    • 感谢ecatmur,这是我最终实施的解决方案,除了我没有费心将我的代码包装在宏函数中,因为有太多东西需要来回传递。实际上,我最初确实考虑过使用宏,但我很犹豫,因为听说它们是一个“坏主意”。另外有人告诉我,他们不能很好地使用 gdb,但是当我遇到它时,我会越过那座桥。
    【解决方案3】:

    首先,typedef 不是一种新类型,它是一个别名或缩写形式,使事情更方便(尤其是在使用函数指针时)

    C 是静态语言,不能在运行时创建类型,需要在编译/链接时解析类型。

    如果可能的话,Windows API 会小很多:)

    在 Windows 中,它们为大多数 API 调用提供了两个版本的函数,并有一个定义来决定使用哪个版本。

    例如

    #ifndef UNICODE
    #define myfunction _myfunctionA(TCHAR* p);
    #else
    #define myfunction _myfunctionW(TCHAR* p);
    #endif
    

    但同样,类型是在编译时决定的

    【讨论】:

      【解决方案4】:

      另一方面,typedef 只能在某些范围内使用。

      int 
      main(void) {
          if (1) {
              typedef short sample;
              sample n; // OK
          }
          sample u; // ERROR
          return 0;   
      }
      

      【讨论】:

        【解决方案5】:

        C(和 C++)中的类型在编译时是固定的; 'runtime typedef' 的概念在 C 中没有意义。

        但是,您的问题可以小心解决。您将定义两组函数(和类型),一组处理 16 位 .wav 文件,另一组处理 32 位 .wav 文件。这些将在编译时定义,类型的大小将在编译时固定,但是这两个代码都将在可执行文件中,您将能够根据运行选择要执行的函数集-时间信息(要求您处理或生成的文件类型)。

        你的两组函数应该是对称的。您也许可以使用某种“类似模板”的机制,以便将同一个文件编译两次,一次用于 32 位代码,一次用于 16 位代码,以确保函数名称的更改一致。

        【讨论】:

          猜你喜欢
          • 2014-05-08
          • 2012-04-18
          • 1970-01-01
          • 2013-05-31
          • 1970-01-01
          • 1970-01-01
          • 2021-10-24
          • 2016-08-30
          • 1970-01-01
          相关资源
          最近更新 更多