bcc32でポインタを操作した際の挙動について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
タカ

bcc32でポインタを操作した際の挙動について

#1

投稿記事 by タカ » 11ヶ月前

初めての質問になります。

bcc32 コンパイラにてC言語の勉強をしていたところ、不可解な現象に遭遇しました。
現象的に、bcc32のバグではないかと考えているのですが、如何でしょうか。

bcc32のバージョン:
Borland C++ Compiler 5.5

質問したいこと:
1.自分のPC以外でも、同様の現象が発生するか
2.何故このような現象が発生するのか(可能であれば)

コード:

#include <stdio.h>

int main()
{
	char a, b;
	char *c;
	
	a=1;
	b=2;
	c = &b;
	c++;
	*c = 3;

	printf( "a:%d\n",&a );/* コメントアウトすると結果が変わる */
	printf( "b:%d\n",&b );
	printf( "c:%d\n",c );

	printf( "a:%d\n",a );
	printf( "b:%d\n",b );
	printf( "c:%d\n",*c );

	return 0;
}
実行結果(コメントアウトしない場合):
a:1638228
b:1638227
c:1638228
a:3
b:2
c:3

実行結果(コメントアウトした場合):
b:1638227
c:1638228
a:1
b:2
c:3

仮説:
a と *cは同じアドレスを差しており、 *c の変更は a にも反映されるはず。
しかし、 &a を参照する処理がない場合、 *c の変更は a に反映されない。
そのような仕様はC言語には存在しないため、バグではないか。

box
記事: 1722
登録日時: 8年前

Re: bcc32でポインタを操作した際の挙動について

#2

投稿記事 by box » 11ヶ月前

a と *cは同じアドレスを差しており、
論拠は何ですか?
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
みけCAT
記事: 6120
登録日時: 8年前
住所: 千葉県
連絡を取る:

Re: bcc32でポインタを操作した際の挙動について

#3

投稿記事 by みけCAT » 11ヶ月前

ポインタの操作において、
普通の(配列でない)変数は1要素の配列として扱います。 (N1570 6.5.6 Additive operatorsの7)
c++;により、cはbの「1つ次」の要素を指すようになります。
これは範囲外であり、「1つ次」の要素を指すポインタを生むことはOKですが、
それを単項*演算子でデリファレンスしてはいけないと定められています。 (N1570 6.5.6の8)
タカさんのプログラムはこれに違反しており、未定義動作となります。 (N1570 4. Conformanceの2)
未定義動作なので、何が起こってもおかしくなく、bcc32ではなくタカさんのプログラムのバグです。

printf( "a:%d\n",&a );をコメントアウトした場合、
aは最初に1を代入する以外に値を書き換えることもポインタを使うこともなく、
定数として扱うことができると考えられるので、
実際に最適化によりaが定数に置き換わり、範囲外への書き込みによるデータの破壊を免れた可能性が考えられます。

ちなみに、printfで%dに対応するデータとしてポインタを渡すのも、
型の不一致で未定義動作になります。 (N1570 7.21.6.1 The fprintf functionの9)
ポインタを出力するには、void*にキャストして書式%pを使うのがいいでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

タカ

Re: bcc32でポインタを操作した際の挙動について

#4

投稿記事 by タカ » 11ヶ月前

回答ありがとうございます。納得しました。(お恥ずかしい。安易にコンパイラを疑うべきではなかったです)

データの破壊を意図的に起こす実験ではあったのですが、最適化を考慮できていなかったです。
定義した変数にvolatileを付けたところ、データの破壊を確認できました。

返信

“C言語何でも質問掲示板” へ戻る