12万作品が月額500円(税別)で見放題なのはdTVだけ!! >>dTV(外部リンク)

ZIPファイルを作るときにCRC32を算出すると思うのですが、
CRC32の計算方法を教えてください。

よろしくお願いします。

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

A 回答 (2件)

CRCとは巡回冗長検査(じゅんかい・じょうちょう・けんさ)という誤りを検出する方法の1つです。


その他ハッシュ・キーを計算するハッシュ関数としても使うことが出来ます。

今回のCRCは32ビット幅で生成多項式に X32 + X26 + X23 + X22 + X16 + X12 + X11 + X10 + X8 + X7 + X5 + X4 + X2 + X1 + 1 を利用します。
この生成多項式は CRC32 で使われているものです。

1.CRCタイプ
(1)CRCタイプ(CRC32)
(2)生成多項式(0x04C11DB7)
(3)初期値(0xFFFFFFFF)
(4)出力XOR(0xFFFFFFFF)
(5)入力ビット逆転(なし)
(6)出力ビット逆転(なし)
(7)ビット送り(左送り)

// サンプル
#include <stdio.h>
#include <string.h>
#include <limits.h> // CHAR_BIT

// CRC32のテーブル情報
static unsigned long CRC32Table[ 256 ] = {
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD,
0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9,
0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75,
0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011,
0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD,
0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5,
0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81,
0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D,
0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49,
0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1,
0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D,

0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE,
0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072,
0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16,
0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA,
0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE,
0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02,
0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066,
0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E,
0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692,
0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6,
0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A,
0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E,
0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2,
0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686,
0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A,

0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637,
0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F,
0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53,
0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47,
0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B,
0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623,
0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7,
0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B,
0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F,
0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7,
0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B,
0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F,
0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3,

0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640,
0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C,
0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8,
0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24,
0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30,
0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088,
0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654,
0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0,
0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C,
0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18,
0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4,
0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0,
0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C,
0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668,
0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4,
};

// メモリのCRC32コードを計算
extern unsigned long getMemCRC32( unsigned long crc32, unsigned const char buff[], size_t size )
{
while ( size != 0 ){
crc32 = CRC32Table[ (crc32 >> (32 - CHAR_BIT)) ^ *buff ] ^ (crc32 << CHAR_BIT);
buff++;
size--;
}
return crc32;
}

// ファイルのCRC32コードを計算
extern unsigned long getFileCRC32( const char file[] )
{
unsigned long crc32 = 0xFFFFFFFF;
char buff[ 10 * 1024 ];
size_t size;
FILE *fp;

if ( (fp = fopen(file,"rb")) != NULL ){
do {
size = fread( buff, 1, sizeof(buff), fp );
crc32 = getMemCRC32( crc32, (unsigned const char *)buff, size );
} while ( size != 0 );

fclose( fp );
}
return crc32 ^ 0xFFFFFFFF;
}

// メイン関数
int main( void )
{
char file[ 256 ];
char *find;

while ( fgets(file,sizeof(file),stdin) != NULL ){
if ( (find = strchr(file,'\n')) != NULL ){
*find = '\0';
}
printf( "0x%08lX⇒%s\n", getFileCRC32(file), file );
}
return 0;
}

試し方:
ファイル名をフルパスで入力します。
またはパイプやリダイレクションを利用して入力させます。
出力は32ビットの16進8桁とフルパス名が標準出力に表示されます。
    • good
    • 0
この回答へのお礼

わかりやすい解説ありがとうございました!

お礼日時:2009/09/28 16:18

私的ZIPファイル研究所


http://www.tnksoft.com/reading/zipfile/nonarc.php
にCのソースがあります
    • good
    • 0

このQ&Aに関連する人気のQ&A

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

このQ&Aを見た人はこんなQ&Aも見ています

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

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

QCRCのアルゴリズムって、どんな計算するんですか?

こんにちはお世話になります。
私はネットワークに興味があるオジサンです。
先日、データリンク層のプロトコル群を勉強していたとき、誤り訂正でCRCが出てきました。誤り訂正ではパリティーチェックやチェックサム等は聞き覚えがありましたが、CRCは始めて見たので興味を持ち少し調べてみようと思いました。
それが間違いの元でした。
インターネットでCRCの構造を詳しく解説するサイトが少なく、その解説は難しすぎて手におえません。
数学にはめっぽう弱い私には、多項式同士の加減乗除算などは頭痛の肥やしにしかなりません。
今ではCRCが気になって勉強に集中できない状態です。
そこで、表題にもあるCRCのアルゴリズムを、何方か分かり易く教えてくださいませんか。もしくは、CRCのアルゴリズムを簡単に解説している書籍をご存知でしたら教えてください。
カテゴリー(本来は数学系?)が違うかもしれませんが、何卒よろしくお願い申し上げます。

Aベストアンサー

偶数パリティについておさらいすると、1 となるビットの個数が偶
数になるように、検査ビットを定めるというものですよね?で、検
査側では、1 の個数を数えて奇数だとエラーと判断するわけです。

実は、この偶数パリティというチェックのしかたは、CRC の一種な
んです。CRC では、ある特定の生成多項式を使いますが、CRC の生
成多項式として x + 1 を使ったものが偶数パリティです。

多項式の加減乗除で頭痛ということなら、ちょっと説明が厳しいの
ですが、2進数の加減乗除はできるでしょうか?これがだいじょう
ぶなら、1+1=0(つまり、0-1=1)という世界での2進数の加減乗除
を考えるということでも同じです。

この場合、x+1 という多項式は、11 と考えます。(xのi乗の係数
を第iビットの値とみなす)

例えば、10110 というデータに対して、11 という生成多項式で
CRC の検査ビットを求めるには、生成多項式の桁数-1=1ビット
分データを左にシフトして、101100 を得ます。この値を、上の特
殊な2進数の世界で、生成多項式の 11 で割ります。そうすると、
商として 11011、余りとして 1 が得られます。試しにやってみて
ください。この余りを、101100 から引いて(特殊な2進数の世界で
は足すのと同じ)やると、101101 が出ます。これが送るべき符号
ということになります。実際、1の個数は偶数ですので、付け足し
たビットが偶数パリティとなっていることがわかります。

余りの分を引いたわけですから、このデータは 11 で割り切れるは
ずですので、検査側では 11 で割って、余りが 0 であることを確
認すればいいわけです。

この生成多項式の選び方で、検査の能力が変わってきます。やみく
もに選んだら、検査能力がまったくなくなります。通常の CRC は、
それを考慮してうまく多項式を作ってあるというだけのことです。

なぜ 11 なら偶数パリティと同じなのかとか、生成多項式をどう選
べばいいかとかについては、符号理論の勉強が必要です。前者はそ
れほど難しくはないですが。

偶数パリティについておさらいすると、1 となるビットの個数が偶
数になるように、検査ビットを定めるというものですよね?で、検
査側では、1 の個数を数えて奇数だとエラーと判断するわけです。

実は、この偶数パリティというチェックのしかたは、CRC の一種な
んです。CRC では、ある特定の生成多項式を使いますが、CRC の生
成多項式として x + 1 を使ったものが偶数パリティです。

多項式の加減乗除で頭痛ということなら、ちょっと説明が厳しいの
ですが、2進数の加減乗除はできるでしょうか?こ...続きを読む

QCRCの計算方法について

色々なサイトを参考にして、自分なりにCRC-ITU-TでCRCを計算する関数を作成しました。
いまいち理解が浅く、そのCRCの値が正しいのか判断できずに困っています。
以下にソースを載せます。
アドバイスを、どうかよろしくお願いします。


unsigned short Crc(unsigned char *Data, unsigned long num)
{
  unsigned short vCrc;    //CRCを計算する変数
  unsigned char vData;
  unsigned long i;
  int j;

  vCrc = 0;
  vData = 0;  //初期化

  for(i = 0; i <= num; i++){
    vData = *(Data+i);  //1byte読み込み
    for(j = 0; j < 8; j++){

      //CRC計算変数がシフトで桁あふれする場合
      if((vCrc & 0x8000) != 0){
        vCrc = vCrc << 1;  //1bitシフト
        vCrc = vCrc ^ 0x1021;  //多項式とXOR
      }
      else{
        vCrc = vCrc << 1;
      }

      if((vData & 0x80) != 0){
        vData = vData << 1;  //データ変数1bitシフト        
        vCrc = vCrc ^ 0x0001;  //CRC計算変数に1をXOR
      }
      else{
        vData = vData << 1;
      }
    }
  }
  return(vCrc);
}

色々なサイトを参考にして、自分なりにCRC-ITU-TでCRCを計算する関数を作成しました。
いまいち理解が浅く、そのCRCの値が正しいのか判断できずに困っています。
以下にソースを載せます。
アドバイスを、どうかよろしくお願いします。


unsigned short Crc(unsigned char *Data, unsigned long num)
{
  unsigned short vCrc;    //CRCを計算する変数
  unsigned char vData;
  unsigned long i;
  int j;

  vCrc = 0;
  vData = 0;  //初期化

  for(i = 0; i <= num; i+...続きを読む

Aベストアンサー

そうなんですか^^ 失礼しました。以下のコードを実行すると boost のライブラリで計算したもの、Ru-LaLaさんのコードで計算したもの、サンプル実装で計算したものを比較すると、Ru-LaLaさんので計算したものだけ値が違うので、Ru-LaLaさんのコードが間違ってる可能性があるような気がします^^;

サンプルコードは、
 http://page.freett.com/seaside/vip/crc/ProgramC1.htm
から取りました。サンプルコードをパクってしまえばいいのでは?(笑)

====
#include <iostream>
#include <boost/crc.hpp>

unsigned short ProgCrc1(unsigned char* Data, unsigned long StartAdr, unsigned long StopAdr)
{ unsigned short vCRC; /*CRCを計算する変数*/
unsigned char vData; /*CRC計算時に1データ読み込む変数*/

/*初期化*/
vCRC = 0;
vData = 0;
/*CRC書き込み位置の初期化*/
*(Data + StopAdr + 1) = 0;
*(Data + StopAdr + 2) = 0;

/*CRC-ITU-Tの計算*/
for(unsigned long Loop1=StartAdr; Loop1<=StopAdr+2; Loop1++) /*CRC書き込み位置までループ*/
{ vData = *(Data + Loop1); /*1Byte読みこみ*/
/*CRC1Byte計算*/
for(char Loop2=0; Loop2<8; Loop2++)
{/*CRC計算変数がシフトで桁あふれするか確認*/
if((vCRC & 0x8000) != 0)
/*桁あふれ有り*/
{ vCRC = vCRC << 1; /*CRC計算変数1Bitシフト*/
vCRC = vCRC ^ 0x1021; /*生成多項式のXOR*/
}
else
/*桁あふれ無し*/
{ vCRC = vCRC << 1; /*CRC計算変数1Bitシフト*/
}

/*データ変数がシフトで桁あふれするか確認*/
if((vData & 0x80) != 0)
/*桁あふれ有り*/
{ vData = vData << 1; /*データ変数1Bitシフト*/
vCRC = vCRC ^ 0x0001; /*CRC計算変数に1XOR*/
}
else
/*桁あふれ無し*/
{ vData = vData << 1; /*データ変数1Bitシフト*/
}
}
}
*(Data + StopAdr + 2) = (unsigned char)(vCRC & 0x00ff); /*CRCの下位書き込み*/
*(Data + StopAdr + 1) = (unsigned char)((vCRC >> 8) & 0x00ff); /*CRCの上位書き込み*/

return(vCRC);
}
unsigned short Crc(unsigned char *Data, unsigned long num)
{
unsigned short vCrc; //CRCを計算する変数
unsigned char vData;
unsigned long i;
int j;

vCrc = 0;
vData = 0; //初期化

for(i = 0; i <= num; i++){
vData = *(Data+i); //1byte読み込み
for(j = 0; j < 8; j++){

//CRC計算変数がシフトで桁あふれする場合
if((vCrc & 0x8000) != 0){
vCrc = vCrc << 1; //1bitシフト
vCrc = vCrc ^ 0x1021; //多項式とXOR
}
else{
vCrc = vCrc << 1;
}

if((vData & 0x80) != 0){
vData = vData << 1; //データ変数1bitシフト
vCrc = vCrc ^ 0x0001; //CRC計算変数に1をXOR
}
else{
vData = vData << 1;
}
}
}
return(vCrc);
}

unsigned short crc_itu_t(unsigned char *data, unsigned long num)
{
boost::crc_basic<16> calc(0x1021);
calc.process_bytes(data, num);
return static_cast<unsigned short>(calc.checksum());
}

int main()
{
unsigned char data[6 + 2] = { 'a', 'b', 'c', 'd', 'e', 'f' };
std::cout << std::showbase << std::hex;
std::cout << crc_itu_t(data, 6) << '\n';
std::cout << Crc(data, 6) << '\n';
std::cout << ProgCrc1(data, 0, 5) << '\n';
std::cout << static_cast<int>(data[6]) << '\n';
std::cout << static_cast<int>(data[7]) << '\n';
}
====
./a.exe
0x3afd
0x58e1
0x3afd
0x3a
0xfd

そうなんですか^^ 失礼しました。以下のコードを実行すると boost のライブラリで計算したもの、Ru-LaLaさんのコードで計算したもの、サンプル実装で計算したものを比較すると、Ru-LaLaさんので計算したものだけ値が違うので、Ru-LaLaさんのコードが間違ってる可能性があるような気がします^^;

サンプルコードは、
 http://page.freett.com/seaside/vip/crc/ProgramC1.htm
から取りました。サンプルコードをパクってしまえばいいのでは?(笑)

====
#include <iostream>
#include <boost/crc.hpp>

...続きを読む

QCRC32のデータ送りの方向について

 送信されてくるethernetフレームを受信しながらCRC32を計算し、
FCSチェックを実施するハード(VHDLによる)を作成しようとしています。

 ハードの構成は、下記URL(の中程)のような、1bit単位でのxorにより実施しようと考えています。
http://homepage3.nifty.com/izushi/OTN/tn2/index.html

 ethernetフレームで計算されるCRC32が、下記パラメータ、
(1)ビットシフト方向:右
(2)生成多項式:0xEDB88320
(3)初期値(0xFFFFFFFF)
(4)出力XOR(0xFFFFFFFF)
(5)フレームのLSB側(FCSデータが格納されている方)からデータ送り

と一致することは判明し、検証も終わったのですが、
フレームはFCS側からではなく、MSB側(MACアドレス側)から転送されてくるため、
(5)と相反し、実装できません。

フレームのLSB側(FCSデータ側)からではなく、MSB側(MACアドレス側)から
データを送り、(1)~(5)の条件で求めたCRC32の値を再現することはできるのでしょうか?

「CRC32」、「左送り」などで調べてみたのですが、
下記URLのように、MSB側(格納データのアドレス0側)から計算している例も
あったのですが、CRC32の値が(1)~(5)パラメータで求めたものとCRC32の値が異なりました。
http://oshiete.goo.ne.jp/qa/5183760.html

 要約すると、同一のデータを使用して、MSB側、LSB側から計算し、
同じCRC32の値となるようなパラメータの組み合わせが有るか無いか、
ということになると思うのですが・・・

よろしくお願いします。

 送信されてくるethernetフレームを受信しながらCRC32を計算し、
FCSチェックを実施するハード(VHDLによる)を作成しようとしています。

 ハードの構成は、下記URL(の中程)のような、1bit単位でのxorにより実施しようと考えています。
http://homepage3.nifty.com/izushi/OTN/tn2/index.html

 ethernetフレームで計算されるCRC32が、下記パラメータ、
(1)ビットシフト方向:右
(2)生成多項式:0xEDB88320
(3)初期値(0xFFFFFFFF)
(4)出力XOR(0xFFFFFFFF)
(5)フレームのLSB側(FCSデータが格納されている方)か...続きを読む

Aベストアンサー

テーブル変換方式
http://www.efg2.com/Lab/Mathematics/CRC.htm

QチェックサムとCRC

複数のデータを照合する時にチェックサムを使っています。
CRCというやり方もあると聞きましたが、
具体的にはどういうことをやるのでしょうか?
宜しくお願いします。

例えば、シリアル通信とかで8ビットデータが複数送られてきて、
そのデータ群が正しいかどうかをチェックする時。

Aベストアンサー

「CRC アルゴリズム」とかで検索すると出てくるかと。
http://hyphenlink.blog48.fc2.com/blog-entry-53.html とか。

んで…チェックサムの場合は…下記のような場合にエラーが検出されません。

・データの順番が入れ替わった場合。
 00 01 02 03 04 05 06 でチェックサムが15h
   ↓
 00 05 02 03 04 01 06 でもチェックサムは15h

・データの一部が減算されていて、別の一部が同じだけ加算されていた場合。
 00 01 02 03 04 05 06 でチェックサムが15h
   ↓
 04 01 00 00 09 01 06 でもチェックサムは15h

CRCだとデータの並びが変わった場合は算出されるCRC値も異なります。
 00 01 02 03 04 05 06 でCRC32がAD5809F9
 00 05 02 03 04 01 06 でCRC32が52A58EEB
 04 01 00 00 09 01 06 でCRC32が5DD68733

QCRC16計算について

CRC16のプログラムを作ったのでデバッグしていて気付いた事なのですが
(産業装置で使うMODBUS-RTUのソフト)
CRC16 x16+x15+x2+1
生成多項式 0xA001

CRC16でCRCを含めたデータを再CRCするとゼロになると言われておりますが
そうならないのですが何故でしょう?

もちろん、自分の作ったソフトが信用できないので他ソフトで検証


具体例
ベクターにあるCRC16の計算ソフト - CRC16.exe
http://blog.goo.ne.jp/masaki_goo_2006/e/50b20edb79f60964faeaefe6fa064469
これに文字列"ABCD" [0x4142,0x4344]を入れて計算実行

出力結果
 初期値:0xFFFF、出力XOR:0xFFFF、出力結果、右送り0x0F85


この出力を最初の文字列に追加する
0x4142,0x4344,0x0F85

結果は0xc7e6 となってゼロになりません
やりかたが違うのでしょうか?


尚、私の作ったプログラムと上記ソフトの結果が同じです
また、ネット上にある同様な他ソフトでも同じ結果でした
(もちろんCRC計算条件が同じ物)

尚、上記ソフトで
初期値:0x0000、出力XOR:0x0000、左送り:9AA8
この場合のみCRC追加しての再CRCはゼロになりました

ゼロになる場合とならない場合があるのでしょうか?

CRC16のプログラムを作ったのでデバッグしていて気付いた事なのですが
(産業装置で使うMODBUS-RTUのソフト)
CRC16 x16+x15+x2+1
生成多項式 0xA001

CRC16でCRCを含めたデータを再CRCするとゼロになると言われておりますが
そうならないのですが何故でしょう?

もちろん、自分の作ったソフトが信用できないので他ソフトで検証


具体例
ベクターにあるCRC16の計算ソフト - CRC16.exe
http://blog.goo.ne.jp/masaki_goo_2006/e/50b20edb79f60964faeaefe6fa064469
これに文字列"ABCD" [0x4142,0x4344]を入れて計...続きを読む

Aベストアンサー

すみません, 忘れてました.

CRC を計算するときには
1. 与えられたデータの下位 (ビット送りの反対側) に「初期値」を付加する
2. 生成多項式で割って余りを求める
3. 「出力XOR」との排他的論理和を計算する
という手順をとります. つまり,
「初期値:0x0000、出力XOR:0x0000、左送り:9AA8」
は (以下 16進で表記します)
1. データ列 41 42 43 44 に初期値 0000 を付加して 41 42 43 44 00 00 を得る
2. それを生成多項式で割って余り 9AA8 を得る
3. それと出力XOR 0000 との排他的論理和を計算して 9AA8 を求める
として得られた値です.

で, 「CRCを含めたデータを再CRCする」というのはこの場合
データ列 41 42 43 44 9A A8 に対して CRC を計算する
言い替えれば「データ列 41 42 43 44 に対し 9A A8 を初期値として CRC を求める」ということです (初期値の設定ができないので, 質問文に挙がっている CRC16.exe ではこのような計算はできません). 最後にある
「尚、上記ソフトで
初期値:0x0000、出力XOR:0x0000、左送り:9AA8
この場合のみCRC追加しての再CRCはゼロになりました」
はおそらく 41 42 43 44 9A A8 というデータを入力した結果だと思いますが, それは実際には
41 42 43 44 9A A8 00 00
に対して CRC を計算しています (41 42 43 44 9A A8 に対して CRC が 0 になるならこれに対しても 0 になるけど, それは「CRC が想定しているチェック方法」ではない).

ここまでは初期値 0000, 出力XOR 0000 なので簡単ですが, その他の値を使った場合には得られた CRC を「適切に」変化させた値を初期値にしないと「CRCを含めたデータを再CRCするとゼロになる」などという都合のいいことにはなりません.

ところで, 初期値と出力XOR が両方とも 0 なら右送りでも (左送りと同じ事情で) 最終的な CRC を 0 にできるんですけど, どうでしょうか?

すみません, 忘れてました.

CRC を計算するときには
1. 与えられたデータの下位 (ビット送りの反対側) に「初期値」を付加する
2. 生成多項式で割って余りを求める
3. 「出力XOR」との排他的論理和を計算する
という手順をとります. つまり,
「初期値:0x0000、出力XOR:0x0000、左送り:9AA8」
は (以下 16進で表記します)
1. データ列 41 42 43 44 に初期値 0000 を付加して 41 42 43 44 00 00 を得る
2. それを生成多項式で割って余り 9AA8 を得る
3. それと出力XOR 0000 との排他的論理和を計算して 9AA8 を求め...続きを読む

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) {
// ここに処理を書く
}
という関数が必要なようです。

QUDP通信におけるbind関数について

初めて質問させていただきます。よろしくお願いします。

最近、ネットワークプログラミングの勉強をしているのですが、bindについてよくわからなくなってきました・・・。よろしければご教授願います。

質問内容は以下の通りです。
(1)bindにおける設定内容は、「相手側のIPとポート番号」なのか「自分側のIPとポート番号」なのか?
 色々なところを調べてみましたが、「IPとポート番号」を設定する、としかかかれてなく、いったいどっちなのかがわからなくなってきました・・・。

(2)UDP通信において、bindは必要なのか?
 サーバ-クライアントの関係が曖昧なUDP通信において、bindというのは必要なのでしょうか。
私の認識では例えば、「recv関数」などを使い受信待ちをする場合はbindが必要だが、送信だけの場合には不要であるとなっています。

この認識はあっているのでしょうか。
拙文ですが、どうか教えていただきたく <(_ _*)>

Aベストアンサー

TCP/UDP通信がどのように働くかを考えれば、疑問の答えが分かるのでは?
bindについて言えば
「OSはマシンに届いたパケットを如何にして該当プログラムに届けるか?」
です。
自分のポート番号をOSに教えてあげなければ、OSは着信したパケットをどのプログラム(プロセス)に届けるか分からないでしょう。それをするのがbindの役割です。
従って(1)は自ポート番号。IPは複数IPを持っているマシンで一部IPでのみ受け付ける場合に必要ですね。
一般的にサーバでbindするタイミングでは相手のIPやポート番号は不明ですから、要求されても困りますね。
(2)は質問者さんの認識通り。受信のために必要、送信では不要です。

QDWORDの実際の型は何でしょうか

VC++.NETの環境です。
DOWRD dw1 = 1;
int i = 2; と定義し
ここで
if ( i > dw1 ){
何かの処理;
}
とコーディングすると
warning C4018: '>' : signed と unsigned の数値を比較しようとしました。
のワーニングがでます。
これは、DWORDがint型でなくunsigned int型のようにも見えます。
ある本によれば(VC++.V.NET逆引き大全500の極意)
DWORD はint型であると記述されています。
もし、int型ならこのワーニングはでないはずなのですが、
なぜでるのでしょうか。又、DWORDの実際の型は何なのでしょうか。ご存じのかたおりましたら、教えていただけませんでしょうか。

Aベストアンサー

型定義が知りたいのならば、宣言ファイルを見れば疑問を挟む余地もありません。
DWORD型はwindef.hで
"typedef unsigned long DWORD;"
と宣言されています。

Visual Studioを使っているのならば、知りたい型の上にマウスポインタを置いて右クリック、ポップアップメニューの「定義へ移動」または「宣言へ移動」で簡単に知ることが出来ます。

Q4バイトでのサムチェックコード作成プログラミング

下記のようにTx[1]からTx[19]までのサムチェックコードを
Tx[21](上位)、Tx[22](下位)に格納したいのですが上手くいきません。記述の訂正点やもっと良い方法があったら教えて下さい。

unsigned char Tx[30];
unsigned int sum;

for( i = 1; i < 20; i++ ) // サムチェックコード作成
sum ^= Tx[ i ];

Tx[ 22 ] = sum; //23 サムチェックコード2
sum = sum >> 8;
Tx[ 21 ] = sum; //22 サムチェックコード1

Aベストアンサー

^= はサムですから +=の間違いなんでしょうね。

変数のキャストが抜けています。
sum += (int) Tx[ i ];
Tx[ 22 ] = (char) sum;

あと、SUM = 0 と明示的に初期化しましょう。

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);
にするかどちらかですね。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報