興味深い質問です。私自身、これに反則しました。主に、無実のメモリブロックへの疑わしい型キャストを含む恐ろしいハッキングが原因です。
この答えは、実際にはRの答えの当然の結果であり、問題をかなり釘付けにします(ただし、少しはよくわかりませんand goes out of scope after that function ends..
) 。
私にとって、これの鍵は次のことを熟読することです:
(1)ISO C99 6.7.2:
タイプが同じである場合、2つのタイプは互換性のあるタイプになります。2つの型が互換性があるかどうかを判断するための追加の規則は、型指定子については6.7.2、型修飾子については6.7.3、宣言子については6.7.5で説明されています46)。翻訳ユニットは、タグとメンバーが次の要件を満たしている場合に互換性があります。一方がタグで宣言されている場合、もう一方は同じタグで宣言されている必要があります。..。
(2)C名前空間
とにかく、ここにいくつかのコード(〜いくつかの翻訳ユニット)があります。これは、これまでこの問題にまだ遭遇していない人にとって、おそらく驚くべき動作を示すことを願っています。
blah.c:
#include <stdio.h>
struct bar {int a; int b;} stbar;
struct bar_ {int a; int d;} stbar_;
void foo(struct bar* pst);
void foo_(struct bar st);
void callfoo()
{
/*no warnings; possibly surprising results ! */
stbar.a=313;
stbar.b=31313;
foo(&stbar);
printf("called foo() with stbar: %d, %d\n", stbar.a, stbar.b);
/*generates incompatible types warnings:
blah.c:23:5: warning: passing argument 1 of ‘foo’ from incompatible pointer type [enabled by default]
blah.c:6:6: note: expected ‘struct bar *’ but argument is of type ‘struct bar_ *’ */
stbar_.a=313;
stbar_.d=31313;
foo(&stbar_);
printf("called foo() with stbar_: %d, %d\n", stbar_.a, stbar_.d);
/*generates incompatible types warnings:
blah.c:31:5: warning: passing argument 1 of ‘foo’ from incompatible pointer type [enabled by default]
blah.c:6:6: note: expected ‘struct bar *’ but argument is of type ‘struct bar *’ */
struct bar {float s; float t;} stbar;
foo(&stbar);
printf("called foo() with locally defined stbar: %f, %f\n", stbar.s, stbar.t);
}
void callfoo_()
{
stbar.a=313;
stbar.b=31313;
//passing in incompatible type by value ~ no warnings; possibly surprising results !
foo_(stbar);
/*uncomenting next line generates compiler error:
blah.c:47:5: error: incompatible type for argument 1 of ‘foo_’
blah.c:7:6: note: expected ‘struct bar’ but argument is of type ‘struct bar_’ */
//foo_(stbar_);
}
void main()
{
callfoo();
callfoo_();
}
blah_.c:
#include <stdio.h>
struct bar {int x; float z;} stbar;
void foo(struct bar* pst)
{
printf("foo : %d, %f\n", pst->x, pst->z);
pst->x=13;
pst->z=13.13;
}
void foo_(struct bar st)
{
printf("foo_ : %d, %f\n", st.x, st.z);
st.x=13;
st.z=13.13;
}
出力:
$ gcc blah.c blah_.c
blah.c: In function ‘callfoo’:
blah.c:23:5: warning: passing argument 1 of ‘foo’ from incompatible pointer type [enabled by default]
blah.c:6:6: note: expected ‘struct bar *’ but argument is of type ‘struct bar_ *’
blah.c:31:5: warning: passing argument 1 of ‘foo’ from incompatible pointer type [enabled by default]
blah.c:6:6: note: expected ‘struct bar *’ but argument is of type ‘struct bar *’
$ ./a.out
foo : 313, 0.000000
called foo() with stbar: 13, 1095898235
foo : 313, 0.000000
called foo() with stbar_: 13, 1095898235
foo : 13274075, 0.000000
called foo() with locally defined stbar: 0.000000, 13.130000
foo_ : 313, 0.000000
$ gcc --version
gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1 ...
当然の結果:C++の神々を称賛しnamespace
ます。