C 如果另一个typedef';d参数列表中使用类型的名称

C 如果另一个typedef';d参数列表中使用类型的名称,c,gcc,C,Gcc,考虑一个大型项目,其中许多类型是typedef'd,例如 typedef int age; typedef int height; 有些函数获取这些类型的参数: void printPerson(age a, height h) { printf("Age %d, Height %d\n", a, h); } 如果这些参数的类型错误,是否有方法在编译时发出警告,例如 age a = 30; height h = 180; printPerson(h, a); /* No warnin

考虑一个大型项目,其中许多类型是
typedef
'd,例如

typedef int age;
typedef int height;
有些函数获取这些类型的参数:

void printPerson(age a, height h) {
    printf("Age %d, Height %d\n", a, h);
}
如果这些参数的类型错误,是否有方法在编译时发出警告,例如

age a = 30;
height h = 180;
printPerson(h, a); /* No warning, because a and h are both integers */

gcc(或某些静态代码分析工具)是否有选项在这种情况下发出警告?

否,不能。如果你正在做(或即将做)非法的事情,编译器会警告你。它不应该知道(或确定)将作为函数参数传递的值的正确性。只要类型相同,它就没有任何理由抱怨


但是,如果类型不匹配,它会提醒您。

GCC中没有对此的内置支持

根据稀疏
nocast
属性,需要添加此项。然而,这一点尚未得到实施。但是,如果可以使用Sparse,可以通过使用
\uuuuu属性((nocast))
标记每个typedef来实现

<>在C++中,可以通过包装类而不是类型定义来实现,然后不为它们定义隐式转换。

有一些与它们称为“强类型”相关的检查。 对于代码,它抛出STRONG.TYPE.ASSIGN.ARG,因为参数类型不匹配

它还抱怨将
int
值(常数)分配给
age
height
类型化变量,以及在
printf
中使用变量作为
int


不过,我听说它非常昂贵。

只有在类型不同时才会生成错误。您能否将这些类型封装在struct中,并使用宏来自动定义和赋值

如果您愿意使用枚举而不是整数,那么在名为coverity的静态代码分析工具中,有一个选项用于警告使用混合枚举


寻找混合枚举。

正如其他响应所表明的那样,您不会从gcc免费获得此结果。你肯定是进入了静态分析工具的世界来解决这个问题

对于这一点,有几个建议,其中一些需要额外的注释,有些不需要,但可能超出了您的期望。因此,我想我应该在混音中再加一个


各种命令行lint工具一直是我长期的备用工具。在您的情况下,我认为PC lint/flexelint非常适合,即使它是一种商业工具。有关其强类型检查,请参阅。

正如其他人所述,C中不支持此功能。如果您确实希望进行强类型检查,可以这样做:

typedef struct {int a;} age;
typedef struct {int h;} height;

void printPerson(age a, height h)
{
    printf("Age %d, height %d\n", a.a, h.h);
}

age a = {30};
height h = {180};

printPerson(h, a);  // will generate errors

不过,请注意,这可能会对性能产生一些影响。

我认为不会出现警告,因为这两种类型都是兼容的。我认为你的例子过于简单了,因为不清楚为什么会有人这样做!相关:与年龄和身高相关的任何键入定义的int的人都应该被撤销键盘权限。很抱歉你不得不处理这个问题。@qexyn:这只是一个例子。但是等等。。。它有什么问题?@urzeit但我想告诉你的是,它对值不起作用。好吧,但它可能知道,“嘿,h是类型高度,但在参数列表中,它应该是a,程序员可能犯了错误”,并打印出警告(当然,必须由程序员检查)。该工具可能通过仅对代码进行词法分析而不对值进行任何操作来实现这一点。这不是真的,例如,如果您执行
if(foo=bar)
,gcc会发出警告,尽管这是完全合法的。当代码分析器“认为”某些内容不符合预期时,通常会抛出警告。这正是问题所在。至少根据您在答案中链接的功能请求所附带的测试用例,不会检测到OP中的场景。Dang,没错,我已经忘记了这一点<代码>按位可能更有用,但它还有其他含义。似乎需要一个新的属性。这不是我所要求的。在我的例子中,不可能更改类型,因为调用的函数是外部库。您在问题中没有提到这一点。coverity可能会对您有所帮助。这样,我不得不将许多代码从
a
更改为
a.a
,因此这不是一个选项。无论如何,谢谢你。正如我在指针的anwer中所写的,我不能更改所有类型,因为其中一些类型是对外部库函数的调用。