プロが教えるわが家の防犯対策術!

最近話題になってる gcc13.2の挙動。
これってバグなんでしょうか?

それともプロトタイプしっかり前方に書かんと
何が起こるかわからんという教訓?

「gcc13.2のバグ?」の質問画像

A 回答 (5件)

②についてはその通り. C では「使う前に宣言する」ことで一貫している. いわゆる「オブジェクト指向」言語ではそのように限定すると (心理的に) 問題


を生じる可能性があるので若干緩めていると考えられる.

①③は未定義動作に関する話だから, 規格上はいかなる指定もしていない. 未定義動作だから処理系によって挙動が変化することはあり, 実際に GCC と VC とで違う振舞いをするケースもある.

なお ③ については (デフォルトオプションの) GCC でエラーを出すプログラムも書ける.
    • good
    • 1

規格上は #2 の指摘の通り. 少なくとも C99 以降においては


An identifier is a primary expression, provided it has been declared as designating an object (in which case it is an lvalue) or a function (in which case it is a function designator).
(式中で用いる識別子は宣言されていなければならない)
と規定されており, さらに
Thus, an undeclared identifier is a violation of the syntax.
(だから未宣言の識別子を使うのは文法上アウト)
と脚注が付いている.

その時点でもう「ダメ」なプログラムなのだから, そこに「正しい動き」など存在しない. 同時に「『正しくない』動き」も存在しないので, 例えば
いきなり鼻歌を歌いだす
ようなことになったとしても, 文句はいえない.

余談.
そのプログラムにおける「コードの意図」がさっぱりわからん.
    • good
    • 1
この回答へのお礼

まとめるとこうなるのかな?

①c99では暗黙の関数宣言は廃止されたから、本来はコンパイルエラーとなるべき。だけどgccは未だ暗黙の関数宣言を既定では採用し、警告で注意喚起に止めている。
バグというより、互換性をどの辺に置くかの判断の問題?
②関数の呼びたしより、ソース上で「前」に関数の宣言、定義がないと
関数の呼び出しで暗黙の関数宣言が採用される。
#Javaとか後でも良い言語は多いけど、Cは違う
③同一ソースで同名関数に2つの解釈生まれても、c99より前のcではコンパイル可能。パラメー夕の引き渡しでそごが生じることが有る。

③はエラーになると思ってました。
まあ別ファイルだと全くチェックかからないのがCだから
そんなものなのかな。

お礼日時:2023/12/09 17:29

具体的には, どのような「挙動」に対して「バグなんでしょうか?」と問うている?



まあプロトタイプくらい書くのが常識だとは思うが.
    • good
    • 1
この回答へのお礼

>具体的には, どのような「挙動」に対して
>「バグなんでしょうか?」と問うている?

写真の一番最後の行が実行結果で、コードの意図と異なってて
Twitter上で驚きの声が広がっているという話です。

恐らく、関数呼び出しではプロト夕イプなしの解釈、
関数定義ではプロトタイプ有の解釈
で引数が正常に渡らない ということだと思うのですが

Cコンパイラでは同一ソース内で同名の関数に異なる解釈が
生まれても放置というのが正しい動きなのか

というのが質問の主旨です。

お礼日時:2023/12/09 14:12

GCC 5 の変更点に、C言語のデフォルトは C89 から C11 とするとあり


> The default mode for C is now -std=gnu11 instead of -std=gnu89

C99 の変更点に、暗黙的な関数宣言は廃止するとあり
> Major changes in the second edition (__STDC_VERSION__ 199901L)
> - remove implicit function declaration

そのためデフォルト設定の gcc では、
C言語の暗黙的な関数宣言を、規格違反として警告していると推測します。

対策としては
1. 関数は定義や宣言をしてから使うように見直す
2. すべての関数宣言をヘッダ化して冒頭に include させる
3. オプション -std=c90 を指定する

参考)
https://gcc.gnu.org/gcc-5/changes.html
https://www.open-std.org/jtc1/sc22/wg14/www/docs …
    • good
    • 0

ご指摘のバグ某を全く知らないですが、私自身の環境で試してみました。

いずれのgccも私自身でコンパイルしたものです。

$ cat test.c
#include <stdio.h>

void func1 ( void )
{
func2 ( 1.0, 2 );
}

void func2 ( int a, double b )
{
printf ( "%d %f\n", a, b );
}

int main ( void )
{
func1 ();
}
$ gcc --version
gcc (GCC) 10.1.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gcc test.c
test.c: 関数 'func1' 内:
test.c:9:1: 警告: implicit declaration of function 'func2'; did you mean 'func1'? [-Wimplicit-function-declaration]
9 | func2 ( 1.0, 2 );
| ^~~~~
| func1
test.c: トップレベル:
test.c:12:6: 警告: 'func2' と型が競合しています
12 | void func2 ( int a, double b )
| ^~~~~
test.c:9:1: 備考: 前の 'func2' の暗黙的な宣言はここです
9 | func2 ( 1.0, 2 );
| ^~~~~

一方...
$ gcc --version
gcc (GCC) 13.2.0
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gcc test.c
test.c: 関数 'func1' 内:
test.c:9:1: 警告: implicit declaration of function 'func2'; did you mean 'func1'? [-Wimplicit-function-declaration]
9 | func2 ( 1.0, 2 );
| ^~~~~
| func1
test.c: トップレベル:
test.c:12:6: 警告: conflicting types for 'func2'; have 'void(int, double)'
12 | void func2 ( int a, double b )
| ^~~~~
test.c:9:1: 備考: previous implicit declaration of 'func2' with type 'void(int, double)'
9 | func2 ( 1.0, 2 );
| ^~~~~

さらにさらにtest.cをtest.cppにリネームしてみました。

$ mv test.c test.cpp
$ gcc --version
gcc (GCC) 10.1.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gcc test.cpp
test.cpp: 関数 'void func1()' 内:
test.cpp:9:1: エラー: 'func2' was not declared in this scope; did you mean 'func1'?
9 | func2 ( 1.0, 2 );
| ^~~~~
| func1
$ g++ test.cpp
test.cpp: 関数 'void func1()' 内:
test.cpp:9:1: エラー: 'func2' was not declared in this scope; did you mean 'func1'?
9 | func2 ( 1.0, 2 );
| ^~~~~
| func1


$ gcc --version
gcc (GCC) 13.2.0
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gcc test.cpp
test.cpp: In function 'void func1()':
test.cpp:9:1: エラー: 'func2' was not declared in this scope; did you mean 'func1'?
9 | func2 ( 1.0, 2 );
| ^~~~~
| func1
$ g++ test.cpp
test.cpp: In function 'void func1()':
test.cpp:9:1: エラー: 'func2' was not declared in this scope; did you mean 'func1'?
9 | func2 ( 1.0, 2 );
| ^~~~~
| func1

バージョンの違いでメーッセージの内容に違いはないように見えます。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています