如何在不影响性能的情况下实现原始类型的类型安全?

问题描述

我想让 c 编译器检查简单类型的使用情况。我的首选用法是检查 typedef,但即使使用 -Wall-Wextra 也没有这样做:

#include <math.h>
#include <stdio.h>

typedef float deg;
typedef float rad;

float sinus( rad angle ) {
    return sin( angle );
}

int main() {
    deg a = 180;
    printf( "The sinus of %g is %g\n",a,sinus(a));
    return 0;
}

这可以顺利编译。

所以我正在考虑使用单成员结构:

#include <math.h>
#include <stdio.h>

typedef struct { float value; } deg;
typedef struct { float value; } rad;

float sinus( rad angle ) {
    return sin( angle.value );
}

int main() {
    deg a = {.value=180};
    printf( "The sinus of %g is %g\n",sinus(a));
    return 0;
}

这给出了一个彻头彻尾的错误(应该如此)。但是,我想知道性能。如果我更正上述示例,则生成的二进制文件具有相同的大小,无论是否进行优化。但是,生产的组件不同。即使在更复杂的上下文中,编译器能否优化出 struct?如果没有,是否有另一种方法可以实现原始类型的类型安全?

我正在使用 GCC (9.1.0),但如果有帮助,我会考虑使用 llvm。这应该适用于常见的桌面架构,即 x86、x86_64、ARM。

编辑:我注意到您还可以在上面的示例中使用 union 代替 struct。这再次产生略有不同的汇编代码,而且我也不清楚真实世界的性能后果。

解决方法

我想让 c 编译器检查简单类型的使用情况。我的首选用法是检查 typedef,但没有这样做

使用 recent GCC 的一种可能方法可能是在 typedef(或 __attribute__-s)上添加额外的 #pragma 并编写自己的代码GCC plugin 进行检查(可能同时使用 type inferenceabstract interpretation 技术)

请注意,您想要的功能超出了标准 C 的语义,如定义在例如n2176

如果允许(并获得资助),我可能会(在 2021 年春季)扩展 Bismon 静态分析器(在此 DRAFT 报告中描述)以实现您的目标。另请参阅 CHARIOTDECODER 项目。给我发电子邮件至 basile.starynkevitch@cea.fr 了解更多信息。

另一种方法是设计您自己的编程语言,并编写您的编译器 generating C code。然后 ACM SIGPLAN 会议是相关的。

或者根据您的需要调整 Frama-CClang static analyzer

在所有情况下,都要预算几个月的专业软件工程师劳动力。注意Rice's theorem

您梦寐以求的检查可以部分自动化,但需要昂贵的开发成本。

您的问题与 dimensional analysis 有关:以米为单位的距离除以以秒为单位的持续时间得出速度。还有单位(角度可以是弧度和度数)

IIRC,一些航天器因为这样的错误而丢失了。