英文:
Are typedef declarations for bare function types (ie: not function pointers) legal in C89/C90?
问题
以下是您要翻译的代码部分:
#include <stdio.h>
#include <string.h>
typedef int INTFUNC(char *, char *);
INTFUNC lencmp;
int main(void) {
printf("%d\n", lencmp("a", "aaa")); /* -1 */
printf("%d\n", lencmp("aaa", "aaa")); /* 0 */
printf("%d\n", lencmp("aaa", "a")); /* 1 */
return 0;
}
int lencmp(char *s, char *t) {
size_t len1 = strlen(s), len2 = strlen(t);
return (len1 > len2) - (len1 < len2);
}
请注意,这仅包括代码的翻译,没有其他内容。
英文:
Let's consider the following code:
#include <stdio.h>
#include <string.h>
typedef int INTFUNC(char *, char *);
INTFUNC lencmp;
int main(void) {
printf("%d\n", lencmp("a", "aaa")); /* -1 */
printf("%d\n", lencmp("aaa", "aaa")); /* 0 */
printf("%d\n", lencmp("aaa", "a")); /* 1 */
return 0;
}
int lencmp(char *s, char *t) {
size_t len1 = strlen(s), len2 = strlen(t);
return (len1 > len2) - (len1 < len2);
}
This compiles fine without warnings with GCC and compiler flags -std=c90 -pedantic -Wall -Wextra
.
But K&R (2e) don't show such code in their book; they only ever usetypedef
s for function pointers. (Their discussion on p147 is problematic, but that aspect is not the subject of this question.) I don't have access to the C89/C90 standard documents.
According to the C standards documents (C99 TC3 (ISO/IEC 9899:TC3) draft, 6.7.7 ¶7; C11 draft, 6.7.8 ¶7; C17 draft, 6.7.8 ¶7; text identical (modulo formatting) in all three documents):
> All three of the following declarations of the signal
function [from <signal.h>
] specify exactly the same type, the first without making use of any typedef names.
>
>
> typedef void fv(int), (*pfv)(int);
>
> void (*signal(int, void (*)(int)))(int);
> fv *signal(int, fv *);
> pfv signal(int, pfv);
>
For what it's worth, Wikipedia claims:
> [example C++ code with typedef
s for function pointers:]
>
> [...]
> typedef int(Foo::*Foo_pfn)(int,int);
> [...]
> typedef int(*PFN)(int);
> [...]
>
>
> Alternate C and C++ syntax
> ==========================
> The C and C++ syntax [with typedef
s for function pointer types] given above is the canonical one used in all the textbooks - but it's difficult to read and explain. Even the above typedef
examples use this syntax. However, every C and C++ compiler supports a more clear and concise mechanism to declare function pointers: use typedef
, but don't store the pointer as part of the definition. Note that the only way this kind of typedef
can actually be used is with a pointer - but that highlights the pointer-ness of it.
>
> C and C++
> ---------
>
> [...]
> typedef int Fn(char c);
> [...]
> typedef Fn *PFn;
> [...]
>
>
> C++
> ---
> [...]
Their wording ("canonical" vs "every C and C++ compiler supports") can be understood to have the discursive/conversational implicature that allowing typedef
s for bare function types is a compiler extension and not sanctioned by the standards. But is that really so? (One commenter argues that such an implicature is absent.) My quote from the C99 TC3, C11, and C17 standards clearly demonstrates that such typedef
s are legal at least since C99 TC3. Given that K&R (2e) doesn't contain typedef
examples in this style, I wonder: Are typedef
declarations for bare function types (ie: not function pointers) legal in C89/C90? Note that the example "given above" that Wikipedia refers to (not shown in its entirety here) is a C++ example, so it's also possible that it's always been legal in standard C but just not in (some versions of) C++.
Finally, if Wikipedia's characterization of using typedef
s for function pointers as "canonical" is correct, the reason for that might lie in the conspicuous lack of typedef
s for bare function types in K&R (2e).
答案1
得分: 3
"typedef"声明的裸函数类型(即:不是函数指针)在C89/C90中是合法的。
请参阅C89标准的内容:
3.7.1 函数定义
语法
function-definition: declaration-specifiers<opt> declarator declaration-list<opt> compound-statement
约束
在函数定义中声明的标识符(即函数的名称)必须具有函数类型,如函数定义的声明符部分所规定的那样。
脚注 70:
意图是函数定义中的顶层类型不能从typedef继承:
typedef int F(void); /* 类型F是``没有参数返回int的函数'' */
F f, g; /* f和g都具有与F兼容的类型 */
F f { /*...*/ } /* 错误:语法/约束错误 */
F g() { /*...*/ } /* 错误:声明g返回一个函数 */
int f(void) { /*...*/ } /* 正确:f具有与F兼容的类型 */
int g() { /*...*/ } /* 正确:g具有与F兼容的类型 */
F *e(void) { /*...*/ } /* e返回指向函数的指针 */
F *((e))(void) { /*...*/ } /* 同样:括号不相关 */
int (*fp)(void); /* fp指向具有类型F的函数 */
F *Fp; /* Fp指向具有类型F的函数 */
第一行证明了C89标准接受"typedef"函数类型。
英文:
> Are typedef declarations to bare function types (ie: not function pointers) legal in C89/C90?
YES.
See C89 standard:
> 3.7.1 Function definitions
>
> Syntax
>
> function-definition:
> declaration-specifiers<opt> declarator
> declaration-list<opt> compound-statement
>
> Constraints
>
> The identifier declared in a function definition (which is the name
> of the function) shall have a function type, as specified by the
> declarator portion of the function definition./70/
Footnote 70:
> The intent is that the top type in a function definition cannot be
inherited from a typedef:
typedef int F(void); /* type F is ``function
of no arguments returning int '' */
F f, g; /* f and g both have type
compatible with F */
F f { /*...*/ } /* WRONG: syntax/constraint error
*/
F g() { /*...*/ } /* WRONG: declares that g returns a function */
int f(void) { /*...*/ } /* RIGHT: f has type compatible with F */
int g() { /*...*/ } /* RIGHT: g has type compatible with F */
F *e(void) { /*...*/ } /* e returns a pointer to a function */
F *((e))(void) { /*...*/ } /* same: parentheses irrelevant */
int (*fp)(void); /* fp points to a function that has type F */
F *Fp; /* Fp points to a function that has type F */
The first line proves that the typedef
ing function types is accepted by C89 standard.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论