为什么这个程序不产生任何警告?

发布于 2024-12-05 10:37:43 字数 321 浏览 6 评论 0原文

#include<stdio.h>
void jigar (int ji)
{
    printf("%d",ji);
}
void main()
{
int a=32;
(jigar)(a);
}

当我使用 -Wall 选项运行该程序时,编译器不会给出任何警告或错误,它工作正常。但是当我在MIPS交叉编译工具链中编译这个程序时,它给出了一个错误:

(jigar)(a);

在这一行。现在我的问题是:为什么 gcc for linux 没有指出我的愚蠢错误?

#include<stdio.h>
void jigar (int ji)
{
    printf("%d",ji);
}
void main()
{
int a=32;
(jigar)(a);
}

When I run this program with the -Wall option, the compiler doesn't give any warning or error, it works fine. But when I compile this program in MIPS cross-compiler tool chain, then it gives an error:

(jigar)(a);

at this line. Now my question is: why gcc for linux doesn't point out my silly mistake?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

陌生 2024-12-12 10:37:43

(jigar)(a); 没有任何问题,因为它在标准 C 中是可以接受的。您的 MIPS 编译器发出警告的原因是因为该编译器可能没有完全实现标准 C。

编辑:关于 Als 的请求为什么这是标准 C,具体方法

如下:查看 ISO C 语法:http://www.cs.dartmouth.edu/~mckeeman/cs48/mxcom/doc/notation/c.html 并注意函数调用

postfix-expression -> postfix-expression ( )
                    | postfix-expression ( argument-expression-list )

可以有 后缀表达式 作为函数。有一条规则说:

postfix-expression -> primary-expression

其中primary-expression可以是标识符,即函数名称。然而,还有这条规则:

primary-expression -> ( expression )

如果您遵循表达式中的规则链,您将再次返回primary-expression。因此,间接地,您可以得到:

primary-expression -> ... -> ( primary-expression ) -> ( identifier )

C 的语义表明 ( expression )expression (1) 具有相同的类型和值。根据语法,(jigar)(a)是正确的。从语义上讲,(jigar)jigar 具有相同的类型和值。因此,C 接受 (jigar)(a) 并且功能与 jigar(a) 相同。

编辑2:

(1)C99草案第6.5.1节第5条:

带括号的表达式是主要表达式。 其类型和值与不带括号的表达式的类型和值相同它是左值、函数指示符或void表达式如果未加括号的表达式分别是左值、函数指示符,或空表达式。

PS 有人知道我在哪里可以获得 ISO C 的文档,比如功能列表之类的吗?我看到有人引用它,但我自己找不到。

There's nothing wrong with (jigar)(a); as it is acceptable in standard C. The reason your MIPS compiler gives warning is because perhaps that compiler does not fully implement standard C.

Edit: Regarding Als's request for why this is standard C, here's how:

Look at the ISO C grammar here: http://www.cs.dartmouth.edu/~mckeeman/cs48/mxcom/doc/notation/c.html and note that a function call

postfix-expression -> postfix-expression ( )
                    | postfix-expression ( argument-expression-list )

can have postfix-expression as function. There is a rule that says:

postfix-expression -> primary-expression

where primary-expression could be an identifier, that is function name. However there is also this rule:

primary-expression -> ( expression )

and if you follow the chain of rules from expression you get back at primary-expression again. Therefore indirectly, you have:

primary-expression -> ... -> ( primary-expression ) -> ( identifier )

The semantics of C indicates that ( expression ) has the same type and value as expression (1). According to the grammar, (jigar)(a) is correct. Semantically, (jigar) and jigar have the same type and value. Therefore C accepts (jigar)(a) and the functionality is the same as jigar(a).

Edit 2:

(1) C99 draft section 6.5.1 article 5:

A parenthesized expression is a primary expression. Its type and value are identical to those of the unparenthesized expression. It is an lvalue, a function designator, or a void expression if the unparenthesized expression is, respectively, an lvalue, a function designator, or a void expression.

P.S. anyone knows where I can get the documentation for ISO C, like a list of features or something? I have seen people quote it, but I couldn't find it myself.

╰沐子 2024-12-12 10:37:43

为什么(jigar)(a);不给出警告或错误?

对于符合标准 C 的编译器来说,这是完全可以接受的构造(我并不是说 gcc 就是这样)。
这只是函数名称周围的一对额外的冗余括号,解析为与函数名称本身相同的东西......或者被更多的括号包围。

/* assuming `jigar` is a honest-to-God function
** all 3 statements below "do" the same thing */
jigar(a);
(jigar)(a);
(((((((jigar)))))))(a);

我已经看到它在现实生活中用于防止宏扩展(不过这个例子是现在编造的)。

#include <stdio.h>

#define MACRO(x) ((x) - 42)

int (MACRO)(int x) { return 42 + x; } /* does not expand MACRO! */

int main(void) {
    printf(" MACRO  ==> %d\n", MACRO(100));   /* expand */
    printf("(MACRO) ==> %d\n", (MACRO)(100)); /* do not expand */
    return 0;
}

您可以看到上面的代码在 codepadideone

并且 main 返回 int,而不是 void.

why (jigar)(a); does not give warning or error?

That's a perfectly acceptable construct for a Standard C conformant compiler (which I'm not claiming gcc is).
That's just a pair of extra redundant parenthesis around the function name, resolving to the same thing as the function name by itself ... or surrounded by even more parenthesis.

/* assuming `jigar` is a honest-to-God function
** all 3 statements below "do" the same thing */
jigar(a);
(jigar)(a);
(((((((jigar)))))))(a);

I've seen it used in real-life to prevent macro expansion (the example was made up right now though).

#include <stdio.h>

#define MACRO(x) ((x) - 42)

int (MACRO)(int x) { return 42 + x; } /* does not expand MACRO! */

int main(void) {
    printf(" MACRO  ==> %d\n", MACRO(100));   /* expand */
    printf("(MACRO) ==> %d\n", (MACRO)(100)); /* do not expand */
    return 0;
}

You can see the code above running on codepad and on ideone.

And main returns int, not void.

吖咩 2024-12-12 10:37:43

我在您的代码中看到的唯一错误是您的 main 返回 void,而 它应该返回 int

gcc 4.4.3-Wall 会选择这个。

如果您指的是 (jigar) 周围的括号,那么它是有效的 C。如果您的 MIPS 编译器不喜欢它,那么这是 MIPS 编译器的问题。

The only error that I see in your code is that your main returns void, whereas it should return int.

gcc 4.4.3 with -Wall picks this up.

If you're referring to the parentheses around (jigar), it's valid C. If your MIPS compiler doesn't like it, then it's a problem with the MIPS compiler.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文