在C语言中,排除const/restrict限定符的外部函数声明是否与原始声明等效?

在C语言中,排除const/restrict限定符的外部函数声明是否与原始声明等效?,c,C,例如,fwrite具有以下签名: size\u t fwrite(const void*ptr、size\u t size、size\u t nmemb、FILE*stream); 如果我宣布: size\t fwrite(void*ptr、size\t size、size\t nmemb、FILE*stream); (省略常量) 如果给定一个非常量参数,是否可以保证它的行为仍然相同 是的,我知道正确的做法是包括标题,但出于这个问题,我假设这不是一个选项。C 2018 6.7.6.3 15说

例如,
fwrite
具有以下签名:

size\u t fwrite(const void*ptr、size\u t size、size\u t nmemb、FILE*stream);
如果我宣布:

size\t fwrite(void*ptr、size\t size、size\t nmemb、FILE*stream);
(省略常量)

如果给定一个非常量参数,是否可以保证它的行为仍然相同


是的,我知道正确的做法是包括标题,但出于这个问题,我假设这不是一个选项。

C 2018 6.7.6.3 15说:

对于要兼容的两种功能类型,两者都应指定兼容的返回类型。此外,参数类型列表(如果两者都存在)应在参数数量和省略号终止符的使用方面保持一致;相应参数应具有兼容类型

因此,我们在
size\t fwrite(const void*ptr、size\t size、size\t nmemb、FILE*stream)中看到
fwrite
size\t fwrite(void*ptr、size\t size、size\t nmemb、FILE*stream)中的
fwrite
兼容
const void*
必须与
void*
兼容

C 2018 6.7.6.1 2规定:

对于要兼容的两种指针类型,两者都应具有相同的资格,并且都应是指向兼容类型的指针

由于
const*
void*
的限定条件不同,因此它们不兼容,因此上面的两个
fwrite
声明不兼容

此外,C 2018 6.5.2.2 9中提到,关于调用函数:

如果函数定义的类型与表示被调用函数的表达式所指向的类型(表达式的类型)不兼容,则行为未定义

这意味着,如果使用上面的一个声明调用
fwrite
,但使用另一个声明定义(用实现函数的块替换分号),则C标准不会定义该行为

注 C 2018 6.7.6.3 15包括:

…(在确定类型兼容性和复合类型时,使用函数或数组类型声明的每个参数被视为具有调整后的类型,使用限定类型声明的每个参数被视为具有其声明类型的非限定版本。)


这不适用于
fwrite
声明。它表示,例如,如果某个参数使用
const
限定,则在确定兼容性时会忽略该参数。因此
const size\u t size
实际上与
size\u t size
相同。但是,在
const void*ptr
中,参数不是
const
限定的;它是指向
常量
限定类型的指针。如果参数
ptr
const
const void*const ptr
const void*const ptr
,C 2018 6.7.6.3 15规定:

对于要兼容的两种功能类型,两者都应指定兼容的返回类型。此外,参数类型列表(如果两者都存在)应在参数数量和省略号终止符的使用方面保持一致;相应参数应具有兼容类型

因此,我们在
size\t fwrite(const void*ptr、size\t size、size\t nmemb、FILE*stream)中看到
fwrite
size\t fwrite(void*ptr、size\t size、size\t nmemb、FILE*stream)中的
fwrite
兼容
const void*
必须与
void*
兼容

C 2018 6.7.6.1 2规定:

对于要兼容的两种指针类型,两者都应具有相同的资格,并且都应是指向兼容类型的指针

由于
const*
void*
的限定条件不同,因此它们不兼容,因此上面的两个
fwrite
声明不兼容

此外,C 2018 6.5.2.2 9中提到,关于调用函数:

如果函数定义的类型与表示被调用函数的表达式所指向的类型(表达式的类型)不兼容,则行为未定义

这意味着,如果使用上面的一个声明调用
fwrite
,但使用另一个声明定义(用实现函数的块替换分号),则C标准不会定义该行为

注 C 2018 6.7.6.3 15包括:

…(在确定类型兼容性和复合类型时,使用函数或数组类型声明的每个参数被视为具有调整后的类型,使用限定类型声明的每个参数被视为具有其声明类型的非限定版本。)


这不适用于
fwrite
声明。它表示,例如,如果某个参数使用
const
限定,则在确定兼容性时会忽略该参数。因此
const size\u t size
实际上与
size\u t size
相同。但是,在
const void*ptr
中,参数不是
const
限定的;它是指向
常量
限定类型的指针。如果参数
ptr
在您建议的签名中是
void*const ptr
const void*const ptr
的,则参数
ptr
将是
const
限定的。参数名称如何解析?是的,它是相同的。C中没有命名参数(但它们可以为人类读者服务),顺便说一句,这里有
原型中缺少我在新声明中添加了参数名,只是为了避免混淆。是的,这样可以。但是,与之相反,真正的定义是:
size\t fread(void*ptr,size\t size,size\t nmb,FILE*stream)
和虚假的定义是
size\t fread(const void*ptr,size\t size,size\t nmb,FILE*stream)