利用規約の変更について

C言語で、リングバッファを使ってデバックをしたいのですが、どうやったらよいかまったくわかりません。教えてください。よろしくお願いいたします。

このQ&Aに関連する最新のQ&A

A 回答 (8件)

・static変数を使ったデバッグ方法の質問なのか


・リングバッファのデバッグ方法の質問なのか
を整理しないと、有用なアドバイスは出てこないと思います。

後者なら、具体的にどんな問題が起きているのか、どうリングバッファを作られたのかの情報も必要でしょう。一口にリングバッファと言っても、満杯と空の状態を区別の仕方などに複数の選択肢があるので。

状況を整理して、上司の方に相談し、それでも問題が解決しなければ再度質問されることをおすすめします。
    • good
    • 0

もしかして・・・リングバッファを用いた通信ソフトを作って(といっても通信ソフトのログ管理にリングバッファ使うのはふつうのことだけど)、デバッグ情報をそれに送るということでしょうか?


仮に当たってたとして今の質問者さんには難しいと思うし、その手のものは既に作られてたりするので、それを使用した方が簡単だと思う(WindowsだとDbgMonやDbgViewとか)し、fprintfが一番お手軽そうな。
    • good
    • 0

確かに、リングバッファーとデバッグ(デバックではなく)方法とはあまり関係なさそうな気がしますね。


その方法を提案された方に相談してみてはどうでしょうか。
もしかすると、いい知恵を授けてくれるかもしれませんし、思いつきでそう言っていただけかもしれません。
    • good
    • 0

今の状態だとリングバッファをデバッグに用いる以前に、実装したリングバッファのデバッグをしないといけなそう。



#1の補足読んでもログを残すのにリングバッファ関係しそうもないけど・・・
    • good
    • 0

「リングバッファって何?」ってとこから始めなければならないのなら、そのアプローチを考え直した方がいいでしょうね。


つーかリングバッファについては検索で沢山説明が出てくるので、いちいちそこの説明は行いません。

もっとも、リングバッファが理解できたらこの質問は解決したも同然でしょうが……
    • good
    • 0

リングバッファーというデータ構造を使ったプログラミングがしたい、ということでしょうか。

    • good
    • 0

リングバッファとデバッグのつながりを説明して下さい。

意味不明です。
    • good
    • 0

漠然としすぎた質問にどう答えたらよいものか……。



まず、リングバッファってどういうものかは理解されていますか?
デバッグの対象がなんなのか説明できますか?

この回答への補足

すみません。説明不足でした。
リングバッファを作成して、デバックでブレイクをかけたい部分に、static int aがあるとすれば、a=1などとして値をいれ、それをデバック情報として、リングバッファに入れて、ログを残すというものです。

プログラムを実行して、バッファの値を見ると処理がどのように通過しているのか、ログで確認することが出来るといったものです。


上司にこういう風に、デバックしたら良いよ言われたのですが、リングバッファを使ったことがなく困っています。どうぞよろしくお願いいたします。

補足日時:2012/05/25 12:28
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qリングバッファって何ですか

こんばんわ。
素人な質問ですが教えてください。

『リングバッファ』とは何ですが?

<言葉から連想されるイメージは以下のようなものです>
丸いバッファ?
領域サイズが固定されており、容量がいっぱいになったら、
書き込むアドレスを最初の位置に戻し、古い記憶から順に
上書きされていくもの…?

詳しく教えて頂きたく思います。
お願い致します。

Aベストアンサー

こんにちは。

> こんなイメージを持ったのですが、間違っていますか?

イメージは正しい(間違ってはいない)と思います。
※当方の認識不足の場合はすみません。

リングバッファは、通信処理などでも使用されます。
※リングバッファを使用することで、送信処理と受信処理を別々に行うことが
 可能となります。
※また、データの取り逃し防止、処理の渋滞回避などのためにも有効です。

参考までに、リングバッファ使用のサンプルプログラムを作成してみました。
※文字列を登録するリングバッファを使用したものです。
※C言語によるベタな作り方です。
 C++ならクラス化するとか、STLなどを使用して、もっとスマートな作り方が
 できると思います。

これで、リングバッファの動作が、ご理解いただければ良いのですが。。。
※的外れな内容でしたらすみません。

■サンプルの処理の流れ
1)リングバッファの初期化
   ↓
2)リングバッファに10個の文字列を登録
 ・リングバッファの登録数いっぱいまで登録
   ↓
3)リングバッファより1個目のデータ(文字列)を取り出して表示出力
   ↓
4)リングバッファへ11個目の追加データ(文字列)を登録
   ↓
5)リングバッファより2個目のデータ(文字列)を取り出して表示出力
   ↓
6)リングバッファへ12個目の追加データ(文字列)を登録
   ↓
7)リングバッファより3個目のデータ(文字列)を取り出して表示出力
   ↓
8)リングバッファへ13個目の追加データ(文字列)を登録
   ↓
9)リングバッファより残りのデータ(文字列)全部を表示出力

なお、今回のサンプルでは、リングバッファへのアクセスは時系列で順番に
行っていますが、
マルチスレッドのような並列処理で、書き込み処理と、読み込み処理を、別々
に行うような場合は、リングバッファへの同時アクセスを回避するために、
排他制御(片方が使用している場合は、もう片方を使用不可とする)が必要な
場合があります。

■サンプルプログラム
注)インデント等のため、全角スペースを入れています。
  ※コピペする際は、半角スペースorタブに置換して下さい。

=========================
/*
* tring10.c : リングバッファのテスト
*/
#include <stdio.h>
#include <string.h>

#define RING_SIZE 10  /*リングバッファのデータ登録数(上限値)*/
#define SBUF_SIZE 50  /*リングバッファ内の文字列バッファサイズ*/

#ifdef TRUE        /*関数の戻り値の定義(TRUE)*/
#undef TRUE
#endif
#define TRUE 1

#ifdef FALSE      /*関数の戻り値の定義(FALSE)*/
#undef FALSE
#endif
#define FALSE 0

/* リングバッファ構造体 */
typedef struct _T_RING {
  int nSetNum;  /*登録データ数*/
  int nWtPos;    /*書き込み位置*/
  int nRdPos;    /*読み込み位置*/
  char szBuf[RING_SIZE][SBUF_SIZE];  /*文字列バッファ*/
} T_RING;

/* 関数プロトタイプ */
void InitRing( T_RING *t_ring );
int PutRing( T_RING *t_ring, char *szBuf );
int GetRing( T_RING *t_ring, char *szBuf );

/*== main ==*/
int main(void)
{
  int icnt1;  /*カウンタ変数(書き込み用)*/
  int icnt2;  /*カウンタ変数(読み込み用)*/
  char szTemp[SBUF_SIZE];  /*汎用文字列*/
  static T_RING t_ring;  /*リングバッファ*/

  /* 登録データ */
  const char szPutData[][20] = {
    { "Data-01" },    /*01*/
    { "Data-02" },    /*02*/
    { "Data-03" },    /*03*/
    { "Data-04" },    /*04*/
    { "Data-05" },    /*05*/
    { "Data-06" },    /*06*/
    { "Data-07" },    /*07*/
    { "Data-08" },    /*08*/
    { "Data-09" },    /*09*/
    { "Data-10" },    /*10*/
    { "AddData-01" },  /*11*/
    { "AddData-02" },  /*12*/
    { "AddData-03" },  /*13*/
    { "\0" }      /*End*/
  };

  /*リングバッファの初期化*/
  InitRing( &t_ring );

  /*リングバッファへデータ登録*/
  /*※最初に10個分(リングバッファの最大登録数分)*/
  for(icnt1=0; icnt1<RING_SIZE && szPutData[icnt1][0]!='\0'; icnt1++)
  {
    PutRing( &t_ring, (char*)szPutData[icnt1] );
  }

  icnt2 = 0;  /*読み込み用カウンタをリセット*/

  /*リングバッファより1個読み込んで出力*/
  printf( "-- Get Ring (1) --\n" );
  if( GetRing( &t_ring, (char*)szTemp ) ){
    printf( "No.=%3d: %s\n", icnt2+1, szTemp );
    icnt2++;
  }

  /*リングバッファへ追加データ登録(1個目)*/
  if( szPutData[icnt1][0]!='\0' ){
    PutRing( &t_ring, (char*)szPutData[icnt1] );
    icnt1++;
  }

  /*リングバッファより1個読み込んで出力*/
  printf( "-- Get Ring (2) --\n" );
  if( GetRing( &t_ring, (char*)szTemp ) ){
    printf( "No.=%3d: %s\n", icnt2+1, szTemp );
    icnt2++;
  }

  /*リングバッファへ追加データ登録(2個目)*/
  if( szPutData[icnt1][0]!='\0' ){
    PutRing( &t_ring, (char*)szPutData[icnt1] );
    icnt1++;
  }

  /*リングバッファより1個読み込んで出力*/
  printf( "-- Get Ring (3) --\n" );
  if( GetRing( &t_ring, (char*)szTemp ) ){
    printf( "No.=%3d: %s\n", icnt2+1, szTemp );
    icnt2++;
  }

  /*リングバッファへ追加データ登録(3個目)*/
  if( szPutData[icnt1][0]!='\0' ){
    PutRing( &t_ring, (char*)szPutData[icnt1] );
    icnt1++;
  }

  /*リングバッファの残りのデータを出力*/
  printf( "-- Get Ring (4) --\n" );
  for(; GetRing( &t_ring, (char*)szTemp ); icnt2++)
  {
    printf( "No.=%3d: %s\n", icnt2+1, szTemp );
  }

  return 0;
}

/*== リングバッファの初期化 ==*/
void InitRing( T_RING *t_ring )
{
  int i;

  /* リングバッファのメンバデータを初期化 */
  t_ring->nSetNum = 0;
  t_ring->nWtPos = 0;
  t_ring->nRdPos = 0;

  /* リングバッファの文字列バッファをクリア */
  for(i=0; i<RING_SIZE; i++){
    memset( t_ring->szBuf[i], 0, (SBUF_SIZE * sizeof(char)) );
  }
}

/*== リングバッファへのデータ登録 ==*/
int PutRing( T_RING *t_ring, char *szBuf )
{
  /* リングバッファがいっぱいのときは登録しないようにする場合は */
  /* 下記を有効とする */
/*
*  if( t_ring->nSetNum == RING_SIZE ){
*    return FALSE;
*  }
*/
  /* リングバッファの書き込み位置のバッファに引数の文字列をセット */
  strcpy( t_ring->szBuf[t_ring->nWtPos], szBuf );

  /* リングバッファの書き込み位置を+1する */
  t_ring->nWtPos = (t_ring->nWtPos + 1) % RING_SIZE;

  /* リングバッファのデータ登録数を+1する */
  if( t_ring->nSetNum < RING_SIZE ){
    /* データ登録数が上限未満のとき */
    t_ring->nSetNum++;
  }
  else {
    /* データ登録数が上限に達したとき */
    /* ※読み込み位置を書き込み位置と同じにする */
    t_ring->nRdPos = t_ring->nWtPos;
  }

  return TRUE;
}

/*== リングバッファからデータ取得 ==*/
int GetRing( T_RING *t_ring, char *szBuf )
{
  /* リングバッファが空きならFALSEで戻る */
  if( t_ring->nSetNum == 0 ){
    return FALSE;
  }

  /* 引数の文字列にリングバッファの読み込み位置の文字列をセット */
  strcpy( szBuf, t_ring->szBuf[t_ring->nRdPos] );

  /* リングバッファの読み込み位置を+1する */
  t_ring->nRdPos = (t_ring->nRdPos + 1) % RING_SIZE;

  /* リングバッファのデータ登録数を-1する */
  /* ※データ登録数が>0のとき */
  if( t_ring->nSetNum > 0 ) t_ring->nSetNum--;

  return TRUE;
}
=========================

■サンプルの実行結果
-- Get Ring (1) --
No.= 1: Data-01
-- Get Ring (2) --
No.= 2: Data-02
-- Get Ring (3) --
No.= 3: Data-03
-- Get Ring (4) --
No.= 4: Data-04
No.= 5: Data-05
No.= 6: Data-06
No.= 7: Data-07
No.= 8: Data-08
No.= 9: Data-09
No.= 10: Data-10
No.= 11: AddData-01
No.= 12: AddData-02
No.= 13: AddData-03

以上です。参考になれば幸いです。

こんにちは。

> こんなイメージを持ったのですが、間違っていますか?

イメージは正しい(間違ってはいない)と思います。
※当方の認識不足の場合はすみません。

リングバッファは、通信処理などでも使用されます。
※リングバッファを使用することで、送信処理と受信処理を別々に行うことが
 可能となります。
※また、データの取り逃し防止、処理の渋滞回避などのためにも有効です。

参考までに、リングバッファ使用のサンプルプログラムを作成してみました。
※文字列を登録するリングバッフ...続きを読む

Q配列の動的確保

No.847223 reallocについて
No.847300 ポインタについて

と質問させてもらい、御回答をいただき、理解した(つもりな)のですが、以下のことが実現できなくこまっております。
(以前の質問はこれを実現するために質問しました。)


まず配列array[1][20]を用意します(つまり文字列最高20字格納できる要素数1個の配列を用意)。
そして動的にこの配列のサイズを変更して、なにか文字列を入力する毎に、代入するスペースを逐次確保したいわけです。(メモリが溢れない限りスペースを確保しまくる)

そこでcallocやreallocの記述の仕方に困っています。
まず、callocについて

char array[1][20];
char *pn, *pn2;

pn = (char *)calloc(sizeof(array)/sizeof(char),sizeof(char));

このボイドポインタをキャストする部分にchar* と
char** のどちらを使えばいいか、です。



そしてreallocについて、

if( (pn2 = (char *)realloc(pn, sizeof(array)*cnt)) == NULL ){

printf("メモリの確保失敗!\n");
exit(0);
}
pn=pn2;

strcpy(pn[cnt],input);

【ただし、cntは毎回1づつ増加する。】
【inputはchar型の配列で、なんらかの文字列がはいっている。】

としているのですが、これもキャストの仕方がわかりませんし、strcpyで、セグメンテーションフォルトになります。構造体を使ったリスト形式も考えたのですが、reallocの使いかたを覚えたいのであえてこの形式で実現しようとしています。

結局どうしたいかというと、realloc部をforループさせて、cntを1ずつ増加させ、
pn[1][20]
つぎは
pn[2][20]
つぎは
pn[3][20]
とどんどん増やしていきたいわけデス。


すこしわかりにくい説明だとおもいますが、不明点や、言い回しがオカシイ箇所があればご指摘下さい。

No.847223 reallocについて
No.847300 ポインタについて

と質問させてもらい、御回答をいただき、理解した(つもりな)のですが、以下のことが実現できなくこまっております。
(以前の質問はこれを実現するために質問しました。)


まず配列array[1][20]を用意します(つまり文字列最高20字格納できる要素数1個の配列を用意)。
そして動的にこの配列のサイズを変更して、なにか文字列を入力する毎に、代入するスペースを逐次確保したいわけです。(メモリが溢れない限りスペースを確保しまくる)

そこでcal...続きを読む

Aベストアンサー

おっしゃるとおり、第一引数がNULLの場合の動作はmallocです。

typedefをしない場合は、それぞれ

char (*pn)[20] = NULL;



pn = (char(*)[20])realloc(pn, sizeof(char[20])*cnt);

となるのかな。ちと自信ないですが。

Q16進ダンプのプログラム

変数の中身を16進数で1バイトずつダンプするにはどんなプログラムを作ったらいいのでしょうか?
ためしに、こんなプログラムを作ってみました。
#include <stdio.h>
int main()
{
int intdata=10;
char *intptr;

intptr=&intdata;
printf("%02x %02x %02x %02x\n", *intptr,*(iniptr+1),*(intptr+2),*(intptr+3));

return 0;
}
 ところが、これでは実行結果が、
 0a 00 00 00
 となって、思い通りに出力されていないように思います。これは何かプログラムに問題があるのでしょうか?それともこの実行結果でよいのでしょうか?
 僕は、 00 00 00 0aと表示されるかと思っていたのですが・・・。

Aベストアンサー

リトルエンディアン(Little Endian)とビッグエンディアン(Big Endian)という言葉をご存じでしょうか。
2バイト以上のデータ量の数値データの記録方式にはリトルエンディアン(最下位のバイトから記録します。Intel系のプロセッサがこの記録方式です。)とビッグエンディアン(リトルエンディアンと逆で、最上位のバイトから記録します。Motorola系のプロセッサがこの記録方式です。)があります。

0a 00 ?? ??となったのはIntel系のプロセッサだからです。??と書いたのは、ここには何が来るか不明だからです。00 00 00 0aを期待していますが、int intdate=10;としているので結果は2バイトですよね。
ビッグエンディアンを期待するのであれば、00 0a ?? ??です。

Q配列動的確保

結論から申しますと,aaa[値1][値2][値3][値4]配列を動的に確保したいのです.

unsigned short *****aaa;
という方法では確保できるのですが,unsigned short ****aaaとようにしてできるのでしょうか?

この他にも違う方法があればご教授ください.

どうぞよろしくお願いいたします.

Aベストアンサー

unsigned short ****aaa;
では、アドレスを保存する領域は確保されますが、
実際にデータを格納するメモリ領域まで確保される訳ではありません。

malloc関数でメモリ領域を確保しないと、
何時アプリケーションエラーを起こすかわからない
危険なプログラムが出来上がります。

aaa = malloc( sizeof( unsigned short **** ) * 値1 ) ;
for (i=0 ; i<値1 ; i++ ) {
aaa[i] = malloc( sizeof( unsigned short *** ) * 値2 ) ;
for (j=0 ; j<値2 ; j++ ) {
aaa[i][j] = malloc( sizeof( unsigned short ** ) * 値3 ) ;
for (k=0 ; k<値3 ; k++ ) {
aaa[i][j][k] = malloc( sizeof( unsigned short * ) * 値4 ) ;
for (l=0 ; l<値4 ; l++ ) {
aaa[i][j][k][l] = malloc( sizeof( unsigned short ) ) ;
}
}
}
}

こんな感じで領域確保をしないと駄目です。
これは処理の途中で値1~4の値が全てわかる時の例です。
処理が進むたびに領域が必要になる場合は、
当然のことながら、その都度メモリ領域を確保する様にしなければなりません。

unsigned short ****aaa;
では、アドレスを保存する領域は確保されますが、
実際にデータを格納するメモリ領域まで確保される訳ではありません。

malloc関数でメモリ領域を確保しないと、
何時アプリケーションエラーを起こすかわからない
危険なプログラムが出来上がります。

aaa = malloc( sizeof( unsigned short **** ) * 値1 ) ;
for (i=0 ; i<値1 ; i++ ) {
aaa[i] = malloc( sizeof( unsigned short *** ) * 値2 ) ;
for (j=0 ; j<値2 ; j++ ) {
aaa[i][j] = malloc( sizeof( un...続きを読む

QLNK2019: 未解決の外部シンボルのエラーが出る

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自キャラのデータ
Point2D g_jikipos = {40, 400};//自キャラの座標

//画像ハンドル
int g_jikiimage[11];

//色々なファイルの読み込み
int LoadFiles(){
//画像ファイル読み込み
if(LoadDivGraph("media\\player01.bmp",
11,11,1,64,64,g_jikiimage) == -1) return -1;

return 1;
}


 mymain.h
//他から呼び出させるMyMainの関数
void MyMain();
int LoadFiles();


 myhelper.h(サンプルなので打ちミスはない)
#include "DxLib.h"
#include <limits.h>
#include <math.h>

//構造体宣言
//座標またはベクトルを記録する構造体
struct Vector{
float x,y;
};
typedef Vector Point2D;
//線を記録する構造体
struct Line2D{
Point2D startpos, endpos;
float katamuki;//傾きをラジアン値で記録
Vector speed;//移動している場合は速度をセット
};
//球体を記録する構造体
struct Ball2D{
Point2D position;
float hankei;//半径
};
//四角形を記録する構造体
struct Rect2D{
Point2D lefttop;
Point2D rightbottom;
float width;
float height;
};


//ライブラリ関数
Point2D PosInView(Point2D in);
int XInView(float inx);
int YInView(float iny);
void ScrollToLeft(float jikiposx);
void ScrollToRight(float jikiposx);
void ScrollToUp(float jikiposy);
void ScrollToDown(float jikiposy);
void DrawLineInView(float x1, float y1, float x2, float y2, int Color, int Thickness);
void DrawCircleInView(float x, float y, float r, int Color, int FillFlag);
void DrawAnimation(float x, float y, double ExtRate, double Angle,int TurnFlag,
int *imgarray, int allframe, float fps);
//ベクトル関数
Vector CreateVector(Vector in, float veclen);
Vector AddVector(Vector v1, Vector v2);
Vector SubVector(Vector v1, Vector v2);
Vector AddVectorInFrameTime(Vector pos, Vector speed);
Vector AddVectorInFrameTime2(Vector pos, Vector speed, Vector accel);
Vector Normalize(Vector in);
Vector RotateVector(Vector in, float radian);
float VectorLengthSquare(Vector in);
float DotProduct(Vector v1, Vector v2);
float CrossProduct(Vector v1, Vector v2);
void SetLine2DKatamuki(Line2D *in);
void DrawLine2D(Line2D in, int Color, int Thickness);
void DrawBall2D(Ball2D in, int Color, int Fill);
//当たり判定関数
bool HitTestLineAndBall(Line2D linein, Ball2D ballin);
bool IsPointAtLineFace(Line2D linein, Point2D ptin);
bool HitTestLineAndLine(Line2D line1, Line2D line2);
bool HitTestBallAndBall(Ball2D a, Ball2D b);
bool HitTestPointAndBox(Rect2D rect, Point2D pt);
//タイマー関数
void SetSimpleTimer(int idx, int time);
int GetPassedTime(int idx);


//グローバル変数
extern float g_frametime;
extern Rect2D g_framerect;//画面領域(当たり判定)
extern Point2D g_current_field_pos;//現在の左上座標
extern Rect2D g_stagesize;//ステージサイズ

//定数宣言
const float ZEROVALUE = 1e-10f;
const float PIE = 3.1415926f;
const int SCROLL_LIMIT = 200;
----------------------------------------------------------------
 エラー内容
1>myhelper.obj : error LNK2019: 未解決の外部シンボル "void __cdecl MyMain(void)" (?MyMain@@YAXXZ) が関数 _WinMain@16 で参照されました
1>C:\Documents and Settings\Owner\My Documents\Visual Studio 2008\Projects\my\Debug\my.exe : fatal error LNK1120: 外部参照 1 が未解決です
1>my - エラー 2、警告 0
ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ
----------------------------------------------------------------
画像を貼り付けときます
(見えにくい場合→http://www.dotup.org/uploda/www.dotup.org154142.jpg.html)
初心者なのでわかりやすくお願いします

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自...続きを読む

Aベストアンサー

ファイル構成から推測するに
mymain.cpp というファイルに
void MyMain(void) {
// ここに処理を書く
}
という関数が必要なようです。

Qprintf による16進表示について

C言語初心者です。

今作っているプログラムで、データを16進形式で表示しようとしています。
大体このような感じです。

/*入力時*/
char buf[5]={0x4e,0x94,0xa0,0x2b,0x78}

/*出力時*/
for (i = 0; i < 5; i++) {
printf("0x%02x\n",buf[i])
}

実際には入力後にある処理によってbufは更新されるのですが、printfの出力結果として、

0xffffff4e
0x94
0xffffffa0
0x2b
0x78

というように、'ffffff'が付加したものがいくつか出力されてしまいます。
これはどういった意味を持つのでしょうか?

なんか初心者ならではの漠然とした質問ですいません。。。

Aベストアンサー

出力は、
0x4e
0xffffff94
0xffffffa0
0x2b
0x78
ではありませんか?
char が符号付(-128~127)のため、0x80~0xffは負の数とみなされます。printfの引数になる時に 符号付charは符号付intに変換されますが、このCコンパイラの場合は、int が4バイトcharが1バイトのため、上位3バイトに負の数を示すffffffが入ります。
char x=255;
printf("%d\n",x);
だと255でなく、-1が表示されます。

対応としては、
unsingned char buf[5]={0x4e,0x94,0xa0,0x2b,0x78}
;
とするか、
printf("0x%02x\n",buf[i]&0xff);
にするかどちらかですね。

QC言語 キューのキーボード操作

(表示するプログラムであるprint_queue_mtrxは分割されています)
以下のプログラムのswitchによるキーボード操作部分について質問します。
このプログラムは「キーボード」による文字入力を行った場合はswitchがちゃんと機能し、キーボードの操作(0,1,他)を加えることができますが、
 リダイレクションでファイル(data.dat)の中の文字列を読みこませた場合、switchが機能することなく、終了します。(キューが機能するのみ)
data.datの中は一行の英字文字列、例えば「TOKYO」のようなものです。
これをリダイレクション(queue < data.dat)で機能どのように記述すればいいでしょうか。

#include <stdio.h>
#include <stdlib.h>

#define MAX 100

void print_queue_mtrx( char *q, int top, int rear );/* top == rear ならばキューは空
キューの値は,top/rearの値が増える方向に積まれていく */

void enqtoQueue( char ch );
char deqfromQueue();
char peekofQueue();
void initializeQueue();

char queue[ MAX ];
int top = 0;
int rear = 0;

void enqtoQueue( char ch )
{
if ( MAX <= rear ) {
fprintf( stderr, "Queue Overflow!!\n" );
exit( 1 );
}
queue[ rear ++ ] = ch;
}

char deqfromQueue()
{
if ( ! ( top < rear ) ) {
fprintf( stderr, "No data in queue!!\n" );
exit( 1 );
}
return queue[ top ++ ];
}

char peekofQueue()
{
return queue[ top ];
}

void initializeQueue()
{
top = 0;
rear = 0;
}

int main()
{
int ch;

/* 1文字ずつ読み込む */
while ( ( ch = getc( stdin ) ) != EOF ) {
switch( ch ) {
case '\n':/* 改行コード除け :) */
break;

case '0':/* 0 の場合はプログラム終了 */
exit( 0 );
break;

case '1':/* 1 の場合は1文字デキューして,その文字を表示して,キューの内容を表示 */
printf( "deqfromQueue: %c\n", deqfromQueue() );
print_queue_mtrx( queue, top, rear );
break;

default:/* それ以外の場合は1文字エンキューして,キューの内容を表示 */
enqtoQueue( ch );
print_queue_mtrx( queue, top, rear );
break;
}
}

return 0;
}

(表示するプログラムであるprint_queue_mtrxは分割されています)
以下のプログラムのswitchによるキーボード操作部分について質問します。
このプログラムは「キーボード」による文字入力を行った場合はswitchがちゃんと機能し、キーボードの操作(0,1,他)を加えることができますが、
 リダイレクションでファイル(data.dat)の中の文字列を読みこませた場合、switchが機能することなく、終了します。(キューが機能するのみ)
data.datの中は一行の英字文字列、例えば「TOKYO」のようなものです。
これ...続きを読む

Aベストアンサー

あぁ、そうか。質問者さんは根本的な事を判ってないんだ。

「入力リダイレクトは、途中からキーボード入力に切り替える事は出来ない」と言うのを判ってないんですね。

例えば、
・入力リダイレクトでファイルから「TOKYO」を読む
・その後、キーボードから「1」か「0」を入力する
と言う事は「普通ではできません」よ。

現状のままでは
・入力リダイレクトでファイルから「TOKYO」を読む
・入力リダイレクトでファイルが尽き、EOFになる
・getc(stdin)がEOFを返すのでwhileループが終了し、プログラムが終了する
と言う動作をします。

リダイレクトするファイルの中に、動作コマンドとなる「1」や「0」も入れておくか、以下のように書かなければなりません。

#include <stdio.h>
#include <stdlib.h>

#define MAX 100

void print_queue_mtrx( char *q, int top, int rear ); /* top == rear ならばキューは空
キューの値は,top/rearの値が増える方向に積まれていく */

void enqtoQueue( char ch );
char deqfromQueue();
char peekofQueue();
void initializeQueue();

char queue[ MAX ];
int top = 0;
int rear = 0;

void print_queue_mtrx( char *queue, int top, int rear )
{
int i;
if (top == rear) return;
printf("---Contents of Queue---\n");
for (i = rear - 1;i >= top;i--) {
printf("%c",queue[i]);
if (i == top) printf("<----Top(%d)\n",top);
else if (i == rear - 1) printf("<----Rear(%d)\n",rear);
else printf("\n");
}
printf("-----------------------\n");
}

void enqtoQueue( char ch )
{
if ( MAX <= rear ) {
fprintf( stderr, "Queue Overflow!!\n" );
exit( 1 );
}
queue[ rear ++ ] = ch;
}

char deqfromQueue()
{
if ( ! ( top < rear ) ) {
fprintf( stderr, "No data in queue!!\n" );
exit( 1 );
}
return queue[ top ++ ];
}

char peekofQueue()
{
return queue[ top ];
}

void initializeQueue()
{
top = 0;
rear = 0;
}

int main()
{
int ch;

/* 1文字ずつ読み込む */
while ( ( ch = getc( stdin ) ) != EOF ) {
switch( ch ) {
case '\n': /* 改行コード除け :) */
break;

case '0': /* 0 の場合はプログラム終了 */
exit( 0 );
break;

case '1': /* 1 の場合は1文字デキューして,その文字を表示して,キューの内容を表示 */
printf( "deqfromQueue: %c\n", deqfromQueue() );
print_queue_mtrx( queue, top, rear );
break;

default: /* それ以外の場合は1文字エンキューして,キューの内容を表示 */
enqtoQueue( ch );
print_queue_mtrx( queue, top, rear );
break;
}
if (ch == '\n') break; /* 改行が来たらリダイレクト終了 */
}

freopen("CON","r",stdin); /* 標準入力をコンソールに切り替え */

/* 1文字ずつ読み込む */
while ( ( ch = getc( stdin ) ) != EOF ) {
switch( ch ) {
case '\n': /* 改行コード除け :) */
break;

case '0': /* 0 の場合はプログラム終了 */
exit( 0 );
break;

case '1': /* 1 の場合は1文字デキューして,その文字を表示して,キューの内容を表示 */
printf( "deqfromQueue: %c\n", deqfromQueue() );
print_queue_mtrx( queue, top, rear );
break;
}
}

return 0;
}

あぁ、そうか。質問者さんは根本的な事を判ってないんだ。

「入力リダイレクトは、途中からキーボード入力に切り替える事は出来ない」と言うのを判ってないんですね。

例えば、
・入力リダイレクトでファイルから「TOKYO」を読む
・その後、キーボードから「1」か「0」を入力する
と言う事は「普通ではできません」よ。

現状のままでは
・入力リダイレクトでファイルから「TOKYO」を読む
・入力リダイレクトでファイルが尽き、EOFになる
・getc(stdin)がEOFを返すのでwhileループが終了し、プログ...続きを読む

Qfloat型とdouble型の変数の違いを教えてほしいです

float型とdouble型の変数の違いを教えてほしいです
2Dゲームを作っててdoubleの変数を使ってたんですが使ってはだめだと先輩に言われたんです。
理由を聞いたら、先生が「doubleは使わないほうがいい」と言われたらしくてちゃんとした理由がわかりませんでした。
それを知って何をするということではないんですが、気になって調べても出てこなかったので質問させてください。
まだゲーム作りを始めたばっかりでぜんぜん詳しくないですが教えてくれたら助かります。

Aベストアンサー

doubleとfloatでは、精度が違い、そのためメモリに占める大きさも違います。
また、一般的には、桁が多いとその分計算時間がかかります。
ですから、精度が必要ない場面では、floatを使う、というのも一つの考えかたです。

ですが、実際には「一概に言えない、処理系依存」です。

以前は全てCPUで計算していたので、精度=計算量でした。
しかし、最近では浮動小数点演算専用の回路が付いているケースが多く、計算時間は同じだったり、doubleに変換が必要でその分floatの方が遅かったり、floatでの演算はより高速にできたり、と様々です。
32bitCPUでは、32bitのfloatの方が扱いやすいでしょうが、64bitCPUでは64bitのdoubleの方が扱いやすいかもしれません。
Cのmath.hで使える標準関数はdouble型のものがほとんどです。三角関数は2Dのゲームでも使う機会が多いのではないでしょうか。sinもcosもdouble型です。内部演算は当然doubleですので、変数にfloatを使ったからと早くはならず、むしろfloat型の変数に入れるときに暗黙の型変換が発生する分遅くなる可能性もあります。

そういった背景を考え検討した結果、floatを使う方がよい、と判断したのならいいのですが、「先生に言われた」では理由になりません。
聞けるのなら、その先生に理由を聞いてください。真意がわからないうちは、鵜呑みしないことです。

doubleとfloatでは、精度が違い、そのためメモリに占める大きさも違います。
また、一般的には、桁が多いとその分計算時間がかかります。
ですから、精度が必要ない場面では、floatを使う、というのも一つの考えかたです。

ですが、実際には「一概に言えない、処理系依存」です。

以前は全てCPUで計算していたので、精度=計算量でした。
しかし、最近では浮動小数点演算専用の回路が付いているケースが多く、計算時間は同じだったり、doubleに変換が必要でその分floatの方が遅かったり、floatでの演算はより高速...続きを読む

Q文字列がNULLか空文字列かの判定

Visual C++で、Cのプログラムを作成しているものです。(OS:WinNT 4.0)
文字列の扱いについて、質問します。

関数 int func(char *str) があると仮定します。
パラメータとして、strは以下のような状態あるとします。
(strは関数が呼ばれる前にcalloc()で領域確保済み)
 シンボル名 値
 str      0x00000001 ""
上記の状態で、strがNULLか空文字列("")であることを条件式にしたいのですが、str == NULL は偽となり、strcmp(str, "") を使用すると異常終了します。
どうしたらよいのでしょうか。アドバイスをお願いします。

Aベストアンサー

No1の方の回答にあるように、calloc()で取れた領域のアドレスを正しく渡せてないように思えますが...

#defineERROR(-1)

int func(char *str)
{
  if( (!str) || (!strlen(str)) ) return ERROR;
  return strlen(str);
}

void main()
{
  char *p=(char*)calloc(10,10);
  printf("%d\n",func(p));
}

Q「memcpy」と「strcpy」について

C言語の初心者です。
先日、課題として以下のようなことを言われました。

「memcpyとstrcpyについて、メモリ破壊が起こるとしたら
どんな場合が考えられるか、簡単にまとめて報告してみて下さい。」
と言われました。

私にはメモリ破壊というニュアンスが分からないのですが、
どちらの関数も必要以上にコピーを行ったときに
起こるメモリ破壊ということなのでしょうか?
それとも、何か特別な意味があるのでしょうか?

C言語に詳しい方がいましたら、是非、教えて下さい。
宜しくお願いします。

Aベストアンサー

 メモリ破壊とは、「当然そこに入っているべき値」を、不用意に上書きしてしまうことです。

 たとえば、char a[100]; という宣言をしたとします。

 memcpy( a, 0, 200 );

 すると、このような実行を行った場合、変数 a の後ろにどんなメモリが存在しているのかプログラマは知ることができないのに、変数 a の後ろの未定メモリ100バイトを上書きしてしまいます。

 この未定メモリには、もしかしたら別の変数があるかもしれませんし、プログラムの一部があるかもしれません。あるいはOSのシステム領域かもしれません。
 どのみちプログラムは正常に動かなくなります。
 通常はメモリエラーが出て停止しますが、最悪の場合、メモリ上のOSを破壊してリセットするしかなくなったりもします。

 これがメモリ破壊です。


人気Q&Aランキング

おすすめ情報