标准库函数定义为宏的参数类型错误 [英] Wrong argument type to a standard library function defined as macro
问题描述
这是示例代码:
#include <ctype.h>
int main(void)
{
isalpha("X");
}
我的问题是:该代码是否违反约束?同样,如果不发出诊断程序,实现是否不合格?
My question is: Is this code a constraint violation? Equivalently, is an implementation non-conforming if it does not issue a diagnostic?
动机:即使是一致的代码,也没有多个主要的编译器对此代码发出警告. C11 6.5.2.2/2涵盖了将char *
传递给原型期望为int
的函数是违反约束的情况.
Motivation: Multiple major compilers don't warn for this code, even in conforming code. C11 6.5.2.2/2 covers that passing char *
to a function with prototype expecting int
is a constraint violation.
但是,我不清楚7.1.4中允许将库函数另外定义为宏的规定是否取代了6.5.2.2/2的要求.脚注187表明该宏隐藏了原型,但脚注是非规范性的.
However it is not clear to me whether the provisions in 7.1.4 allowing a library function to be additionally defined as a macro supersede the requirement of 6.5.2.2/2. Footnote 187 suggests that the macro hides the prototype, but footnotes are non-normative.
代码(isalpha)("X");
确实可以提供诊断信息.
The code (isalpha)("X");
does give a diagnostic of course.
推荐答案
我认为这里的关键是是否允许将isalpha
定义为宏. C11 7.1.4简要提及
I think the key here is whether isalpha
is allowed to be defined as a macro or not. C11 7.1.4 briefly mentions
标头中声明的任何函数都可以另外实现为标头中定义的类似函数的宏
Any function declared in a header may be additionally implemented as a function-like macro defined in the header
尽管本章主要涉及命名冲突和多线程问题等.另一方面,C11 7.4表示:
although this chapter is mostly concerned with naming collisions and multi-threading issues etc. On the other hand, C11 7.4 says:
标头声明了几个对字符进行分类和映射的函数.
The header declares several functions useful for classifying and mapping characters.
和C11 7.4.1.2:
and C11 7.4.1.2:
int isalpha(int c);
isalpha 函数...
我认为isalpha
被视为一个函数.或者,如果实现为宏,则必须通过某种实现来确保某种类型的类型检查.
My take is that isalpha
is to be regarded as a function. Or if implemented as a macro, some manner of type check must be ensured by the implementation.
鉴于它是一个函数,因此从那里很明显.对于所有函数,函数调用规则在C11 6.5.2.2中指定:
Given that it is a function, it is pretty clear from there. For all functions, the rules for function call are specified in C11 6.5.2.2:
如果表示被调用函数的表达式的类型确实包含原型, 参数会隐式转换(就像通过赋值一样)为 对应的参数,以每个参数的类型为不合格版本 其声明类型.
If the expression that denotes the called function has a type that does include a prototype, the arguments are implicitly converted, as if by assignment, to the types of the corresponding parameters, taking the type of each parameter to be the unqualified version of its declared type.
请注意好像是通过分配"部分.这使我们找到了简单分配C11 6.5.16.1约束的规则.问题中的代码将在行后等同于赋值表达式,例如int c = (char[]){"X"};
,其中左操作数是算术类型,右操作数是指针.在C11 6.5.16.1中的任何地方都找不到这种情况.
Note the "as if by assignment" part. This leads us to the rules for simple assignment C11 6.5.16.1, constraints. The code in the question would behind the lines be equivalent to an assignment expression such as int c = (char[]){"X"};
where the left operand is an arithmetic type and the right operand is a pointer. No such case can be found anywhere in C11 6.5.16.1.
因此,该代码违反了6.5.16.1的约束.
Therefore the code is a constraint violation of 6.5.16.1.
如果编译器库选择将isalpha
实现为宏,从而由于在赋值期间不执行函数参数的常规左值转换而以某种方式失去了类型检查功能,则该库很可能是不合格的,如果编译器无法生成诊断消息.
If a compiler lib chooses to implement isalpha
as a macro and thereby loses the type check ability somehow by not performing the normal lvalue conversion of function parameters during assignment, then that library might very well be non-conforming, if the compiler fails to produce a diagnostic message.
这篇关于标准库函数定义为宏的参数类型错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!