本ページは公開が終了した情報の複製であり、掲載時点での情報です。本ページに記載されている内容について各所に問い合わせることはご遠慮下さい。
サポート技術情報

[MSVC] Visual C++ 1.5 の README.WRI(8/8)

文書番号: 401978

最終更新日: 1999/08/19


この資料は以下の製品について記述したものです。


この記事は、以前は次の ID で公開されていました: JP401978

概要

この資料は、Visual C++ 1.5 に添付されている README.WRI の以下の章を抜粋した
ものです。
  第 12 章 確認されているランタイムライブラリの不具合

第 12 章 確認されているランタイムライブラリの不具合

setwritemode(_GXOR) の時、円の描画が不正 (NEC 版のみ)

描画モードを XOR, _ellipse の第一パラメータを_GBORDER にすると描画された円の 四隅が欠けます。円周を大きくすると、欠ける位置が変わり、欠ける場所も増えて
きます。
  • _setwritemode() の引数が _GXOR でない時、_setwritemode() 自体がないときには 発生しません。
  • _ellipse() の引数が _GBORDER でない時も発生しません。 例 #include <stdio.h> #include <conio.h> #include <graph.h> void main(void) {
          int rtn;
              _setvideomode( _MAXRESMODE );
              _setcolor( 7 );
              _setwritemode( _GXOR );
              rtn = _ellipse( _GBORDER, 100, 100, 200, 200);
              getch();
              _setvideomode( _DEFAULTMODE );
    
    }

64K バイト以上の配列を使った qsort 関数の不具合

64K バイト以上のある大きさを持つ二次元配列にたいして qsort 関数を実行した時に 結果の配列に空のデータが含まれることがあります。

原因

これはヒュージデータを使用した qsort 関数の不具合です。ヒュージデータを qsort 関数で使用する場合は二次元配列を構造体配列に書き換えることによって回避する
ことが出来ます。
  例
  // cl option needs /AH
  #define ELM 32
  #define TBL ((0xffff / ELM) + 1)
  //char tbl_key[TBL][ELM];
  struct table{char key[ELM];}tbl_key[TBL]; // <- Modified
  int cmpf(const void *c1,const void *c2);
  void main(void)
  {
  ...
          qsort(&tbl_key,TBL,ELM,cmpf);
  }
  int cmpf(const void *c1,const void *c2)
  {
         return strcmp((struct table*)c1, (struct table*)c2);// <- Modified
  }
  //EOF

_polygon 関数の塗り潰しが正常に行われない (NEC 版のみ)

_polygon 関数を使用して polygon の角がビューポートの外に設定されている時
_polygon の塗り潰しが正常に行われません。

_polygon が縦方向に 1 ドット足りない図形を描画する (NEC 版のみ)

_polygon の第一引き数に_GFILLINTERIOR を指定して長方形を描画した時、縦方向
に 1 ドット足りない長方形になります。_GBORDER の時は正常に描画されます。
  例
  struct _xycoord p[4];
    ...
      p[0].xcoord = 0;
      p[0].ycoord = 0;
      p[1].xcoord = 0;
      p[1].ycoord = 1;
      p[2].xcoord = 100;
      p[2].ycoord = 1;
      p[3].xcoord = 100;
      p[3].ycoord = 0;
      _polygon (_GFILLINTERIOR, p, 4)
   _ellipse(_GFILLINTERIOR,,,) の動作
  _ellipse 関数で塗り潰し (_GFILLINTERIOR) を行う時に同色の背景色で塗り潰した場
  合に、完全に塗り潰しを行いません。
  .//Test Program
  ...
          _setcolor(1);
          _ellipse(_GFILLINTERIOR, 100, 100, 400, 400 );
          _setcolor(2);
          _moveto(150, 150);
          _lineto(350, 150);
          printf("「線」を描画しました・n");
          PrnSts_KeyWait();
          _setcolor(1);
          /* 次の _ellipse が正常に表示されない(_lineto で描画した線が残る) */
          _ellipse(_GFILLINTERIOR, 100, 100, 400, 400 );

_setbkcolor() で画面の範囲外まで色が変わる (DOS/V 版のみ)

_setbkcolor を使うと、VGA の場合 (0,0) ~ (639,399) が画面の範囲になるはずですが、この範囲を越えて塗り潰してしまいます。
  例
  #include       <stdio.h>
  #include       <graph.h>
  #include       <conio.h>
  void main( void )
  {
          _setvideomode(_VRES16COLOR);
          _clearscreen(_GCLEARSCREEN);
          _setbkcolor(_BLUE);        /* 問題の関数 */
          _setcolor(3);                     /* 検証の為、最大範囲で  */
          _rectangle(_GBORDER,0,0,639,479); /* 色を変えて枠を書く    */
          getch();
          _setvideomode(_TEXTC80);
  }

原因

これは _setbkcolor が呼び出している BIOS の仕様です。

_pg_chart の仕様について

レゼンテーショングラフィックス関数の中に、折れ線グラフを表示する、
_PG_LINECHART に於いて、外枠なしの折れ線グラフを作成し、項目の最大値に限
りなく等しいデータ(最大値 1.0、データ 0.999 )を連続して設定したときに、
連続したデータの間の線が表示されません。
  例
  #include        <CONIO.H>
  #include        <GRAPH.H>
  #include        <PGCHART.H>
  #define         TEAMS   2
  #define         MONTHS  3
  float __far values[TEAMS][MONTHS] = {
          { .999F, .999F, .671F },
          { .533F, .533F, .401F } };
  char __far *months[ MONTHS ] = { "May", "June", "July" };
  char __far *teams [ TEAMS  ] = { "Cubs", "Reds" };
  void    main( void )
  {
         chartenv env;
         _setvideomode( _MAXRESMODE );
         _pg_initchart();
         _pg_defaultchart( &env, _PG_LINECHART, _PG_POINTANDLINE );
         env.datawindow.border = 0;
         _pg_chartms( &env, months, ( float __far * )values,
                     TEAMS, MONTHS, MONTHS, teams );
         getch();
         _setvideomode( _DEFAULTMODE );
  }

対応

上記のサンプルプログラムの例では、以下のメンバ変数の設定で可能です。
        env.yaxis.autoscale
        env.yaxis.scalemin
        env.yaxis.scalemax
        env.yaxis.scalefactor
        env.yaxis.ticinterval
        env.yaxis.ticformat
        env.yaxis.ticdecimals
直接必要なのは、x軸を定義する _axistype 構造体の scalemax 変数ですが、
この変数を設定するには、autoscale 変数を 0 にする必要があります。0 を
設定しない限りは、autoscale に続く 7 つのメンバ変数が有効になりません。
逆に言うと、最大値を設定するために、その他の設定をおこなう必要があります。
これらの設定する値は、pgchart の座標計算においても使用されている重要な値の
ため省略して記述することはできません。不用意に 0 を設定したり、省略したり
すると実行時にエラーを引き起こす可能性がありますので、値の設定には、気を付
けてください。

浮動小数点エミュレータの演算ミス

以下のサンプルプログラムを、FPU (子プロセッサ)なし、もしくは NO87 環
境変数でコプロを使わせない状態で実行すると tan() 関数の計算結果が一部不正
になります。また、直前の cos() 関数を外すと正常に動作します。
子プロセッサを使用した状態、あるいは直前に cos() 関数を使用しない時には、
tan() 関数は、0.404... を返しますが、子プロセッサを使用せず、直前に cos()
関数の実行がされていると、i が 10 から 18、28 から 36 の時の演算結果が正
負が逆転して返されます。演算式は、ループ中変化のあるものではなく、
正負の逆転する現象がエミュレータを使用した時のみに発生します。
  例
  /*
  options nothing or /Op
  */
  #include       <MATH.H>
  #include       <STDIO.H>
  #define            PI             3.141592653589793
  void   main( void )
  {
         double  theta, t1, t2;
         int                i;
         for( i = -9; i <= 36; i++ )
        {
                 t1 = cos( theta = (double)i * PI / 18.0 );
                 t2 = tan( 22.0 * PI / 180.0 );
                  printf( "\ni = %3d theta = %6.3lf t1 = %6.3lf t2 = %6.3lf",
                          i, theta, t1, t2 );
         }
  }

対応

この現象を回避するためには 87 が使用できない場合に、tan 関数を
 sin()/cos() に書き直す必要があります。

long double 用のベッセル関数は MS-DOS専用

Visual C++ のオンラインヘルプ、マニュアルには、ベッセル関数の互換性について、 long double 用も含めて MS-DOS、Windows および Windows DLL で利用できるように 記述されています。 しかしこれらは誤記で、long double 用のベッセル関数は
MS-DOS 上のみで利用可能になっています。

cl /Fa /G1 で.286p ディレクティブが出力される

Visual C++ 1.0 のコンパイル時にオプション /Fa /G1 /f- を指定しアセンブラリス トを出力すると、その内容に /G2 オプションを指定したときと同様の .286p、.287
のディレクティブがリストされてしまいます。

原因

これは、米国版 Visual C++ 1.0 のコンパイラからある不具合です。

対策

出力されたリストの該当するディレクティブを修正して御利用ください。
/G1 オプションを付けて出力されるコードに、i80286 ニーモニックが含まれて
いることはありません。

_remappalette() で設定した背景色がプログラムの再起動時に再設定される

環境

PC9801 シリーズ版のみ

現象

_setvideomode(_98RESS16COLOR) などのアナログモードの環境において発生。
_remappalette() 関数で、背景色を変更、_setvideomode(_DEFAULTMODE) を実行してプ ログラムを終了する。プログラムの終了時には、_remappalette() で設定した背景色も 黒に戻され終了します。しかし、再度プログラムを実行すると、_setvideomode() の実 行前に、前回設定した背景色が設定されてしまいます。
現象は、同一のプログラムの再起動に関らず発生しますが、単純に _getch() だけのよ うな グラフィックスライブラリ関数を含まないプログラムでは発生しないようです。

再現プログラム

  #include        <stdio.h>
  #include        <conio.h>
  #include        <graph.h>
  void   main( void )
  {
         _getch();
         _setvideomode( _98RESS16COLOR );
         _remappalette( 0, _98BLUE );
         _getch();
         _setvideomode( _DEFAULTMODE );
  }

_setwritemode( _GXOR ) の時、線の描画が正しく行われない (NEC 版のみ)

_setwritemode() で描画のモードを _GXOR から _GPSET に変更して同一の座標に
線をかかせても、正しく線が描かれず、色が混在して表示される事があります。
  例
  #include       <stdio.h>
  #include       <conio.h>
  #include       <graph.h>
  void     main( void )
  {
          _setvideomode( _98RESS16COLOR );
          _setcolor( 7 );
          _getch();
          _setwritemode( _GXOR );
          _moveto( 260,  74 );
          _lineto( 498, 288 );
          _getch();
          _setcolor( 4 );
          _setwritemode( _GPSET );
          _moveto( 260,  74 );
          _lineto( 498, 288 );
          _getch();
          _setvideomode( _DEFAULTMODE );
  }

_rectangle で描画した枠内に、_setpixel() で塗り潰しが異常(NEC 版のみ)

_rectangle( _GBORDER, ... ) で描画した枠内に、_setpixel() で点を複数表示
すると、塗り潰しが途中で停止してしまいます。枠内に表示する点がある程度、
密になると発生します。下記のサンプルプログラムでは、WIDTH の値が 6 以下だと
塗り潰しが完全にできません。
_setpixel() と _fllodfill() の実行順序を逆にすれば現象の回避は出来ます。

回避プログラム

  #include       <STDIO.H>
  #include       <GRAPH.H>
  #include       <CONIO.H>
  #include       <STDLIB.H>
  void    main( int argc, char *argv[] )
  {
         int   WIDTH;
         int   x, y, ofs, color;
         int   fillx, filly;
         WIDTH = atoi( argv[1] );
         WIDTH = (WIDTH<=0) ? 5 : WIDTH;
          printf("%d", WIDTH );
         _setvideomode( _98RESS16COLOR );
         _rectangle( _GBORDER, 1, 1, 638, 398 );
         ofs = 0;
         for( y = 0; y < 398; y+=WIDTH )
                  for( ofs = 0; ofs < (WIDTH*WIDTH); ofs+=WIDTH )
                          for( x = ofs; x < 639; x+=WIDTH )
                                   _setpixel( (short)x, (short)y );
         color = _setcolor( 4 );
         fillx = 77;
         filly = 77;
         if( fillx % WIDTH == 0 )       fillx++;
         if( filly % WIDTH == 0 )       filly++;
         _floodfill( (short)fillx, (short)filly, (short)color );
         _getch();
         _setvideomode( _DEFAULTMODE );
  }

同じ座標で斜線の再描画を XOR モードで行うと斜線が残る事がある (NEC 版のみ)

同一の座標に対して、_setwritemode(_GXOR) の設定で再描画を行えば、線は
消去されるはずであるが、一部点の残ってしまうことがある。以下のサンプル
プログラムでは、(50,50)-(100,100) の線分は、正しく消去されるが、
(0, 0)-(639,399) の線分は、一部点が残ってしまう。
  例
  #include        <GRAPH.H>
  #include        <CONIO.H>
  void    main( void )
  {
          _setvideomode( _98RESS16COLOR );
          _setcolor( 3 );
          _moveto(  50,  50 );
          _lineto( 100, 100 );
          _moveto(   0,   0 );
          _lineto( 639, 399 );
          _getch();
          _setwritemode( _GXOR );
          _moveto(  50 , 50 );
          _lineto( 100, 100 );
          _moveto(   0,   0 );
          _lineto( 639, 399 );
          _getch();
          _setvideomode( _DEFAULTMODE );
  }

Keywords: KBINFO VC15 KB401978
Technology: kbAudDeveloper kbvc150 kbVCsearch

inserted by FC2 system