【问题标题】:Using 'typedef' to ensure logical type safety使用 'typedef' 确保逻辑类型安全
【发布时间】:2013-03-27 18:28:49
【问题描述】:
typedef int A;
typedef int B;

void foo(A arg){}

void main(void){
    B wrongvar = 7;
    foo(wrongvar);
}

根据标准,这种构造是否应该返回警告/错误?最流行的编译器呢?

例子:我们有变量,代表公斤和米,都是'int'类型。我们有一个功能,处理米。我们希望编译器能够捕捉到错误,这些错误与将公斤表示的变量变量传递给该函数有关。

我相信 Ada 处理得很好。现代 C 呢?

【问题讨论】:

  • A typedef 为现有类型赋予新名称;它不会创建新类型。替代名称也指同一类型。因此,所有ABintsigned int 都可以传递给foo(A arg) 而不会发生类型冲突(以及其他可转换为int 的类型,例如enum 类型,也可以是通过而没有引起警告)。
  • void main(void) 应该是 int main(void) -- 任何告诉你使用 void main(void) 的参考资料都是由不太了解 C 的人编写的。
  • @KeithThompson, c99 似乎是support 这个void main(void) 的用法。误解是因为我没有正确标记问题。
  • 在所有版本的 C 标准中,允许但不要求实现以允许其他形式,包括 void main(void)。 C99 无相关变化。但是int main(void) 由符合all 的托管C 实现支持。除非您正在为嵌入式系统编程,否则没有充分的理由使用 void main(void)

标签: c c99 avr-gcc


【解决方案1】:

您可以使用具有一个字段的结构来完全按照您的意愿行事。唯一的“缺点”是如果优化器不优化它们,你可能会浪费 1/2/4/8 字节......

【讨论】:

  • 结构的大小只是其成员变量的大小加上任何填充(如果需要)的总和。如果只有一个成员变量,我认为在空间方面不会有任何开销。
【解决方案2】:

不,您正在处理的是类型规范问题,称为结构等效与名称等效。正如 Dog 所说,您可以做的最接近您想要的事情是使用结构,但是如果编译器选择添加填充(在这种情况下不太可能),这可能会浪费内存。 C 对别名使用结构等价(意味着两种类型是相同的东西),但不同声明的结构的名称等价(具有相同布局的两个结构类型不被视为等价)。

使用结构来执行此操作的示例:

typedef struct {
    double value;
} meters;

typedef struct {
    double value;
} kilograms;

int main(){
    meters m;
    kilograms k = {2}; // initialized
    m.value = 1;
    k = m; // error, can't assign meters to kilos
    return 0;
}

您不妨阅读这篇文章:http://www.joelonsoftware.com/articles/Wrong.html,描述如何帮助避免这些命名约定问题

【讨论】:

  • 类型名称的 _t 后缀由 POSIX 保留。由于类型存在于与变量不同的命名空间中,因此无论如何都没有理由使用独特的后缀。 stackoverflow.com/a/231807/139746
  • 这只是一个半途而废的解决方案,因为有一天一个新手来写k.value = m.value;,却没有深入考虑后果。如果您想获得真正的安全性,您必须定义自己的类(在您的情况下可能将 int 包装为数据成员)和允许的运算符。
  • @V.K.这是 C,不是 C++
  • 糟糕,我忽略了这一点。对不起。
  • 为什么使用结构会浪费内存?例如,使用 gcc,具有单个成员的结构的大小与成员的大小相同。允许使用尾随填充,但通常不应用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-19
  • 1970-01-01
  • 2014-09-04
  • 2021-05-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多