我阅读了标准N1570部分的6.5.2.2 Function calls
,对包含prototype的函数类型的特殊含义感到困惑。精确6.5.2.2(p6)
如果函数是用不包含原型的类型定义的,且升级后的参数类型与升级后的参数类型不兼容,则行为是未定义的,但下列情况除外: -一种晋升类型是有符号整数类型,另一种晋升类型是对应的无符号整数类型,这两种类型的值都是可表示的; -这两种类型都是指向字符类型或空号的限定或非限定版本的指针。
6.5.2.2(p7)
提供了一个使用prototype调用函数的规则:
如果表示被调用函数的表达式具有包含原型的类型,则参数将被隐式转换,就像通过赋值一样,转换为相应参数的类型,将每个参数的类型视为其声明类型的不合格版本。
请考虑以下示例:
struct test_arg{
int a;
};
void test_no_prototype(const struct test_arg a){ }
void test_with_prototype(const struct test_arg a);
void test_with_prototype(const struct test_arg a){ }
int main(){
struct test_arg test = {.a = 42};
test_no_prototype(test); //1 UB?
test_with_prototype(test); //2 Fine?
}
我认为1是UB,因为test_no_prototype
不包括prototype,而test
有不合格的struct test_arg
版本,但是该参数有类型const struct test_arg
,由于不同的限定条件,它与struct test_arg
不兼容。
我认为2很好,因为test_with_prototype
包括prototype,来自6.5.16.1(p1)
的简单赋值约束允许从同一结构的非限定版本分配给限定结构类型的变量。
这似乎很奇怪,就目前而言,我无法想象为什么我们会以不同的方式对待有和没有原型的函数。也许我不正确地理解了规则..。如果是的话,你能解释一下这是什么意思吗?
发布于 2019-03-29 06:09:36
原型一词并不是指在其定义之前的函数声明。它指的是一个函数声明其参数类型的声明(C 2018 6.2.1 2)。
test_no_prototype
有一个原型,因为void test_no_prototype(const struct test_arg a){ }
声明了它的参数const struct test_arg
的类型。
没有原型的声明的一个例子是void test_no_prototype();
。这是一种旧的声明样式,不应在新代码中使用。
https://stackoverflow.com/questions/55419145
复制相似问题