プロトタイプ宣言の仮引数にconst修飾子がなかった話

関数の仮引数(整数型)にて、プロトタイプ宣言にはconst修飾子がついておらず、関数本体にはconst修飾子がついていたとする。

この状態でコンパイルしてリンクしてみたらどうなるだろうか? コンパイル/リンク時にエラーになるのか、警告が出るのか、スルーしてしまうのか?

C言語及びC++の規格に基づく「期待される動作」は分からないのだが、手元のコンパイラXcode 4.6.1付属のclangとgccVisual Studio 2005、Visual Studio 2010)ではスルーすることが多いようだ。

例えばこんなC言語のソースがあったとする。

/* xxxx.c */
#include <stdio.h>
#include "xxxx.h"

void xxxx(const int n, const int m)
{
	(void) printf("%d, %d\n", n, m);
}
/* xxxx.h */
#ifndef XXXX_H_INCLUDED
#define XXXX_H_INCLUDED

extern void xxxx(const int n, int m);

#endif /* ndef XXXX_H_INCLUDED */
/* yyyy.c */
#include "xxxx.h"

int main(int argc, char *argv[])
{
	(void) argv;
	xxxx(argc, argc);

	return 0;
}

関数xxxxの第2引数を見てみると、関数本体にはconst修飾子が付いているが、プロトタイプ宣言には付いていない。

これらのソースを、次のコマンドでビルドしてみた。

# Apple LLVM version 4.2 (clang-425.0.27) (based on LLVM 3.2svn)
clang -Wall -ansi -pedantic -o yyyy xxxx.c yyyy.c

# i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1
# (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)
gcc -Wall -ansi -pedantic -o yyyy xxxx.c yyyy.c
:: Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86
:: Microsoft (R) Incremental Linker Version 8.00.50727.762
:: (Visual Studio 2005 Professional)
cl.exe /GS /W4 /Wp64 /MT yyyy.c xxxx.c

:: Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
:: Microsoft (R) Incremental Linker Version 10.00.40219.01
:: (Visual Studio 2010 Professional)
cl.exe /GS /W4 /MT yyyy.c xxxx.c

clangとgccでは警告されずにビルドが完了した。Visual Studioではコンパイル時に警告が出た。

C++ではどうか? 例えば次のようなソース。

/* xxxx.cpp */
#include <cstdio>
#include "xxxx.h"

void Xxxx::xxxx(const int n, const int m)
{
	(void) std::printf("%d, %d\n", n, m);
}
/* xxxx.h */
#ifndef XXXX_H_INCLUDED
#define XXXX_H_INCLUDED

class Xxxx {
public:
	void xxxx(const int n, int m);
};

#endif /* ndef XXXX_H_INCLUDED */
/* yyyy.cpp */
#include "xxxx.h"

int main(int argc, char *argv[])
{
	(void) argv;
	Xxxx xxxx;
	xxxx.xxxx(argc, argc);

	return 0;
}

メソッド(メンバ関数)Xxxx::xxxxの第2引数を見てみると、メソッド本体にはconst修飾子が付いているが、class宣言側には付いていない。

これらのソースを、次のコマンドでビルドしてみた。

# Apple LLVM version 4.2 (clang-425.0.27) (based on LLVM 3.2svn)
clang -Wall -ansi -pedantic -o yyyy xxxx.cpp yyyy.cpp

# i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1
# (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)
g++ -Wall -ansi -pedantic -o yyyy xxxx.cpp yyyy.cpp
:: Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86
:: Microsoft (R) Incremental Linker Version 8.00.50727.762
:: (Visual Studio 2005 Professional)
cl.exe /GS /W4 /Wp64 /MT yyyy.cpp xxxx.cpp

:: Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
:: Microsoft (R) Incremental Linker Version 10.00.40219.01
:: (Visual Studio 2010 Professional)
cl.exe /GS /W4 /MT yyyy.cpp xxxx.cpp

clangもgccVisual Studioも、警告されずにビルドが完了した。

このあたり、言語規格的にはどうなのだろうか? 何か規定はあるのだろうか? あと、コンパイラのオプションで挙動が変わるか否かについても気になる。