AIX(5.3)の環境でプログラムソースをコンパイルし実行したところ、
コンパイラーのバージョンの違いによる、挙動の違いを発見しました。
これは、コンパイラーの不具合なのでしょうか?
コンパイラーのバージョンは、vacpp 6.0とvacpp 9.0です。
サンプルソースコードと実行結果は以下の通りです
<sample.c>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
int aaa( char * a, char *b,char *c,... )
{
va_list arglist;
char *temp;
printf("1.a=%x\n",&a);
printf("2.b=%x\n",&b);
printf("----------------------\n");
va_start( arglist, a );
printf( "3.%x=%x=%s\n",arglist,*(char **)arglist,*(char **)arglist);
for( ; (temp = va_arg( arglist, char * )) != 0; ){
printf( "%x=%x=%s\n", arglist, temp, temp );
}
va_end( arglist );
printf("----------------------\n");
va_start( arglist, b );
printf( "3.%x=%x=%s\n",arglist,*(char **)arglist,*(char **)arglist);
for( ; (temp = va_arg( arglist, char * )) != 0; ){
printf( "%x=%x=%s\n", arglist, temp, temp );
}
va_end( arglist );
printf("----------------------\n");
va_start( arglist, c );
printf( "3.%x=%x=%s\n",arglist,*(char **)arglist,*(char **)arglist);
for( ; (temp = va_arg( arglist, char * )) != 0; ){
printf( "%x=%x=%s\n", arglist, temp, temp );
}
va_end( arglist );
return 0;
}
int main(void)
{
aaa("1","A","B","C","D",0);
return 0;
}
<コンパイルコマンド>
xlC -o sample sample.cpp
<バージョン6.00実行結果=正しい結果>
1.a=2ff22568
2.b=2ff2256c
----------------------
3.2ff2256c=10002460=A
2ff22570=10002460=A
2ff22574=10002462=B
2ff22578=10002464=C
2ff2257c=10002466=D
----------------------
3.2ff22570=10002462=B
2ff22574=10002462=B
2ff22578=10002464=C
2ff2257c=10002466=D
----------------------
3.2ff22574=10002464=C
2ff22578=10002464=C
2ff2257c=10002466=D
<バージョン9.00実行結果=正しい結果>
1.a=2ff22a48
2.b=2ff22a4c
----------------------
3.2ff22a4c=10000a30=A ←おかしい
2ff22a54=10000a32=B
2ff22a58=10000a34=C
2ff22a5c=10000a36=D
----------------------
3.2ff22a50=10000a32=B ←ただしい
2ff22a54=10000a32=B
2ff22a58=10000a34=C
2ff22a5c=10000a36=D
----------------------
3.2ff22a54=10000a34=C ←おかしい
2ff22a5c=10000a36=D
No.2ベストアンサー
- 回答日時:
> 変数cについても実行結果が違うのですが、この結果もありうると言うことでしょうか?
あり得るんじゃないでしょうか。
どうしてそうなるのかをちゃんと説明するには、コンパイラが生成したバイナリを逆アセンブルしてみる必要があるでしょう。
va_start( arglist, a );~va_end( arglist );とva_start( arglist, b );~va_end( arglist );のコードを消して、cだけを対象にva_start()を使った場合にも結果が異なるようならコンパイラの不具合を疑うところですが。
ちなみに、GCCでコンパイルしたところちゃんとva_start()について警告が出て、下記のような結果になりました。
warning: second parameter of 'va_start' not last named argument
1.a=bffff688
2.b=bffff68c
----------------------
3.bffff694=2fbc=C
bffff698=2fbc=C
bffff69c=2fc0=D
----------------------
3.bffff694=2fbc=C
bffff698=2fbc=C
bffff69c=2fc0=D
----------------------
3.bffff694=2fbc=C
bffff698=2fbc=C
bffff69c=2fc0=D
この回答への補足
ご返答ありがとうございます
その後、いろいろ試してみたのですがfor文をwhile文に変更してみた結果正常に動作しました。
for( ; (temp = va_arg( arglist, char * )) != 0; ){
↓↓↓
while( (temp = va_arg( arglist, char * )) != 0 ){
またfor文のままでもC++とせずCでコンパイルしたところ正常に動作します。
C++でのfor文の使用方法に問題があるのでしょうか?
No.3
- 回答日時:
全然関係ないですけど, このコードって未定義動作の嵐のような気がする.
とりあえず
・ポインタの値を %x で出力しようとしてる
・arglist を無理矢理 char ** にキャストしてる
・可変引数関数に対する実引数の型がおかしい (最後の 0)
あたりは気付く.
No.1
- 回答日時:
va_start()は、引数リストで...の直前の変数(サンプルコードの中ではc)にしか使えません。
それ以外の変数を対象にした場合の動作は保証されていないはずです。したがって、期待したとおりの挙動にならなくても文句は言えません。
この回答への補足
ご回答ありがとうございます
変数cについても実行結果が違うのですが、この結果もありうると言うことでしょうか?
<バージョン6.00実行結果=正しい結果>
----------------------
3.2ff22574=10002464=C
2ff22578=10002464=C
2ff2257c=10002466=D
<バージョン9.00実行結果=正しくない結果>
----------------------
3.2ff22a54=10000a34=C ←おかしい
2ff22a5c=10000a36=D
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# C言語で再起関数とポインタを用いて文字列反転をする方法がわかりません。 4 2023/04/29 20:32
- C言語・C++・C# Cのdoubleの浮動小数点表示について 3 2023/04/17 13:14
- C言語・C++・C# 並列プログラミングのπ計算について 1 2022/07/16 22:30
- C言語・C++・C# Cのオブジェクトファイルの逆アセンブル 5 2023/05/13 01:51
- C言語・C++・C# C 言語の Gauss Jordan 法について 2 2022/12/28 11:16
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
fgetsなどのときのstdinのバッ...
-
C言語のfor文です。 繰り返しの...
-
文字列から空白を取り除きたい...
-
atoi( ) の反対をやりたい
-
charでの計算?
-
DPマッチング
-
間接操作のレベルとは
-
c言語でユーザ関数を利用して入...
-
バイトスワップをやりたい
-
sprintfに同じ変数は使えるか
-
CStringをwchar_tに変換したい
-
strtok関数 自作
-
sprintf関数の作り方
-
C言語、リダイレクト
-
重複文字を出力させない!!
-
Linuxでフォルダ内全ファイル名...
-
ユニコード文字列の分割
-
C言語です
-
C言語の入力した文字を反転させ...
-
3桁区切(コンマ)記号をつけ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
fgetsなどのときのstdinのバッ...
-
charでの計算?
-
C言語のfor文です。 繰り返しの...
-
charからLPTSTRへの変換方法
-
文字列から空白を取り除きたい...
-
C言語の入力した文字を反転させ...
-
'const char *' 型は 'char *' ...
-
配列をnビットシフトする
-
str系関数を使わずに二つの文字...
-
int main()の・・・
-
atoi( ) の反対をやりたい
-
CStringをwchar_tに変換したい
-
c++ 文字列を入力して、一文字...
-
switch文で文字を比較すること...
-
干支のプログラム
-
3桁区切(コンマ)記号をつけ...
-
絶対パスからのファイル名の切...
-
間接操作のレベルとは
-
間接参照のレベルが異なっています
-
型変換
おすすめ情報