• ベストアンサー

ビット構成について

今、ビットについて勉強しているのですが、わからないところがありますので、質問しました。わかる方がいれば、わかりやすく教えてください。(例として、整数xは10とした場合をしてもらえる助かります。) int count_bits(unsigned x){ int count = 0; while (x){ if (x & 1U) count++; x >>= 1; } return (count); } int int_bits(void){ return (count_bits(~0U)); } void print_bits(unsigned x){ int i; for ( i = int_bits() - 1 ; i >= 0; i--) putchar(((x >> i) & 1U) ? '1' : '0'); } 以上 まず、 int count_bits(unsigned x){ int count = 0; while (x){ if (x & 1U) count++; x >>= 1; } return (count); } についてですが、整数Xを10とした場合、私の考えではcount=2となると思うのですが・・・。 次に int int_bits(void){ return (count_bits(~0U)); } についてなのですが、count_bits関数で整数Xを10とした場合count=2となったあと、int_bits関数では全ビットを1にするということみたいですが、count_bits関数でおこなった作業をどうint_bits関数で処理するのかわかりません。 最後が for文の中の、(i = int_bits() - 1 ; i >= 0; i--) についてですが、整数10のときの i = int_bits() はどうなっているのでしょうか?? わかりにくい質問ですみません。 回答宜しくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
noname#50176
noname#50176
回答No.2

>整数Xを10とした場合、私の考えではcount=2となると思うのです >が・・・。 10(10進)=1010(2進)ですから 1010:0+0=0 101:0+1=1 10:1+0=1 1:1+1=2 2で合っています。 >count_bits関数で整数Xを10とした場合count=2となったあと… xが 0 になるまでの右シフト数を求めた後 void print_bits(unsigned x){ int i; for ( i = int_bits() - 1 ; i >= 0; i--) putchar(((x >> i) & 1U) ? '1' : '0'); } を呼び出し、xのすべての桁を表示するために マスクビット(すべて1)を用意しその回数を求めれば 全桁数が求まります。 例えば8ビットであれば、x=10の時、i=(1111111の桁数8)-1=7 で、 00001010 を 7ビット右へシフト時の1ビット目=0※、i=7-1=6 ・ ・ 00001010 を 3ビット右へシフト時の1ビット目=1※、i=3-1=2 00001010 を 2ビット右へシフト時の1ビット目=0※、i=2-1=1 00001010 を 1ビット右へシフト時の1ビット目=1※、i=1-1=0 00001010 を 0ビット右へシフト時の1ビット目=0※ ですね。 putchar(((x >> i) & 1U) ? '1' : '0'); によって ※の、1,0 を評価してそれぞれ文字の'1'と'0’を表示します。

hatenan114
質問者

お礼

ありがとうございます。 やっとわかりました。 またよろしくおねがいします。

その他の回答 (2)

  • asuncion
  • ベストアンサー率33% (2126/6287)
回答No.3

> のi = int_bits() の部分には32が入り、1の歩数をもとめるので、31ということになるのでしょうか? 1の補数とは無関係です。 print_bits関数は、引数で与えた数値の2進表現を左側から走査して、 ビットが立っているorいないを出力する関数です。 お使いの環境が32ビットであるならば、 右から数えて31ビット目~0ビット目の順に、 つまりいちばん左のビットからいちばん右のビットへ向かって 走査するようになっています。

hatenan114
質問者

お礼

ありがとうございます。 理解できました。 またよろしくお願いします。

  • asuncion
  • ベストアンサー率33% (2126/6287)
回答No.1

count_bits関数は、引数で渡した数値を2進数で表わしたときに、 いくつ'1'ビットが立っているかを返す関数です。 したがって、 > についてですが、整数Xを10とした場合、私の考えではcount=2となると思うのですが・・・。 10進数の10を2進数で表わすと1010ですので、2が返ってくるとの お考えは正しいです。やってみればすぐわかりますよね。 int_bits関数は、お使いの環境では整数を何ビットで 表わしているかを返す関数です。 そのために、count_bit関数に~0U、つまりすべてのビットが'1'であるような 値を渡しています。 10の場合とは切り離して考えてください。 > 整数10のときの i = int_bits() はどうなっているのでしょうか?? これも、10の場合とは切り離して考えてください。

hatenan114
質問者

補足

回答ありがとうございます。わかってきました。 ということは、 int int_bits(void){ return (count_bits(~0U)); } についてですが、私の環境では32ビットなので32ということですね。 そうすると、 void print_bits(unsigned x){ int i; for ( i = int_bits() - 1 ; i >= 0; i--) putchar(((x >> i) & 1U) ? '1' : '0'); } のi = int_bits() の部分には32が入り、1の歩数をもとめるので、31ということになるのでしょうか?

関連するQ&A

  • 関数とビット列

    C言語勉強中です。下記本から抜粋したものですが、 関数の流れや、1U、~0Uなどの意味がわかりません。 それぞれ関数の中でどのような処理をしているのでしょうか? scanfで正数入力し、print_bitsにnxを渡し、そこのxを1と&して 2進の0か1を表示させるのはなんとなく解るのですが、PCのCPUの ビット数を確認する為?の動きなどがわかりません。 どうか、解説していただける方、よろしくお願いします。 #include <stdio.h> int count_bits(unsigned x) {     int count = 0;     while (x) {           if (x & 1U) {              count++;           }           x >>= 1;      }      return (count); } int int_bits(void) {      return (count_bits(~0U)); } void print_bits(unsigned x) {      int i;      for (i = int_bits() - 1; i >= 0; i--) {           putchar(((x >> i) & 1U) ? '1' : '0');      } } int main(void) {      unsigned nx;      printf("非負の整数を入力してください:");      scanf("%u", &nx);      print_bits(nx);      putchar('\n');      return (0); }

  • unsigned型のビット構成を表示するプログラムが理解できません。

    unsigned型ビット構成の表示プログラム #include<stdio.h> int count_bits(unsigned x) { int count=0; while(x){ if(x&1U)count++; x>>=1; } return(count); } int int_bits(void) { return(count_bits(~0U)); } void print_bits(unsigned x) { int i; for(i=int_bits()-1;i>=0;i--) putchar(((x>>i)&1U)?'1':'0'); } int main(void) { unsigned nx; printf("非負の整数を入植してください。:"); scanf("%u",&nx); print_bits(nx); putchar('\n'); return(0); } このプログラムで10を入力したら、00000000000000000000000000000001010と表示され。 18だと00000000000000000000000000000010010と表示される原理が理解できません。 自分なりにプログラムを追ってこういう考えてます。 まず、10を入力したらcount_bitsの関数の処理からスタート。 while(x){ if(x&1U)count++; x>>=1; if(x&1U)の処理を行い。x=10はbit単位表示で、1010として考え。一番右側の101「0」とunsigned型の1との論理比較を行う。0と1なので偽で何もせずにif文を抜けて、x>>=1;を行いx=0101となり。while(x)から再びif(x&1U)行う。x=0101の一番右側のunsigned型の1との論理比較を行い0と1なので真なのでcount++を行いcount=1としてif文を抜け、x>>=1;を行いX=0010になり。三度目のif(x&1U)の処理を行う。0010の一番左側のunsigned型の1との論理比較を行い0と1なので偽でif文を終了。x>>=1;を行い0001となり、再びif(x&1U)行う。 00 01の一番左側のunsigned型の1との論理比較を行い0と1なので真なのでcount++を行いcount=2となり、x>>=1;を行い0000なのでwhile(x)を抜けて返り値2をint_bitsへ返して関数は終了 int_bitsではunsinged型の2が戻り値としてprint_bitsへ返し、int_bitsの関数は終了。 print_bitsの処理が始まり。for(i=int_bits()-1;i>=0;i--)の処理がスタート。 i=int_bits()-1の処理でiは2-1でi=1からスタート。 putchar(((x>>i)&1U)?'1':'0');の処理。 (x>>i)でx=10,i=1なので1010>>1だから0101。 0101の一番右側の1とunsigned型の1と論理比較を行う 真なのでputcharは'1'を一度表示。 for文に戻りiをデクリメントとしてi=0なのi>=0から 一度、putchar(((x>>i)&1U)?'1':'0');処理。 (x>>i)は0101>>0の0右シフト行い0101。 unsignedと1を0101の一番右側の1と論理比較を行う 真なのでputcharは'1'を一度表示。 for文に戻りiをデクリメントとしてi=-1なのでi>=0からfor文を終了してprint_bitsの処理を終了。mainの関数処理に戻り。putchar('\n');を出力して関数処理は終了。表示として「11」が表示される。18も同様に考えているので、「11」が表示されてしまうのでは?という考えに陥ってます。実際は、両方とも正しくunsigned型ビット構成の表示されるので、自分の考え方が間違えている。なのですが、どう間違えているかがわかりません。 多少説明文の省略しているためわかりにくいかもしれませんが、間違えを指摘していただけないでしょうか?

  • 困っています

    どうしても、--unsigned型のビット内容表示--の所が意味が分かりません。分かりやすく教えてください。宜しくお願いします。 /* 0~UINT_MAXを2進・8進・16進で表示 */ #include <stdio.h> #include <limits.h> /*--- 整数xのセットされたビット数を返す ---*/ int count_bits(unsigned x) { int count =0; while (x) { if (x & 1u) count++; x>>=1; } return (count); } /*---- unsigned型のビット数を返す ----*/ int int_bits(void) { return (count_bits(~0U)); } /*---- unsigned型のビットを内容を表示 ---*/ void print_bits(unsigned x) { int i; for (i=int_bits() -1; i>=0; i--) putchar(((x>>i) & 1U) ? '1' : '0'); } int main(void) { unsigned i; for (i=0; i<UINT_MAX; i++) { print_bits(i); printf(" %6o %5u %4X\n", i, i, i); } return(0); }

  • c言語による2のべき乗

    右、左シフトと2のべき乗による乗除算が同じことを証明するプログラムを作っているのですがうまくいきません。 プログラムを載せるのでどこが間違っているのかご教授お願いします。 #include <stdio.h> int count_bits(unsigned x){ int count = 0; while(x){ if(x&1U) count++; x>>=1; } return(count); } int int_bits(void){ return(count_bits(~0U)); } void print_bits(unsigned x){ int i; for(i=int_bits()-1; i>=0; i--) putchar(((x>>i)&1U) ? '1' : '0'); } int main(void){ unsigned nx, no, n1, n2; printf("非負の整数を入力してください:"); scanf("%u", &nx); printf("何ビットシフトしますか?:"); scanf("%u", &no); n1=nx * (2^no); n2=nx / (2^no); printf("\n整数 = "); print_bits(nx); printf("\n左にシフトした値 = "); print_bits(nx << no); printf("\n右にシフトした値 = "); print_bits(nx >> no); printf("\n2のべき乗で乗算した値 = "); print_bits(n1); printf("\n2のべき乗で除算した値 = "); print_bits(n2); putchar('\n'); return(0); }

  • C言語 unsigned 表示

    #include<stdio.h> int count_bits(unsigned x){ int count=0; while(x){ if(x&1U){ count++; } x>>=1; } return count; } int int_bits(void){ return(count_bits(~0U)); } unsigned rrotate(unsigned x1 ,int n){ int bits=int_bits(); n%=bits; return(n? (x1>>n)|(x1<<(bits-n)):x1); } int main (void){ unsigned nx,b; b=rrotate(nx,2); printf("%u\n",b); return(0); } 3221225476や1073741829と表示されることがあります。 入力値を4で割った数を表示するには、どうしたらよいでしょう・ 御指摘お願いします。

  • ビット操作について

    void print_bit(unsigned x) { for(int i=int_bit()-1;i>=0;i--) { putchar(((x>>i) & 1U)?'1':'0');      } } int main(void) { print_bit((~0>>16)); return0; } と入力したのですが、結果が 111111111111111111111111111111 と出てしまうのですが。 自分的には0000000000000000111111111111111と出したいのですが。 どうしたらいいのでしょうか? できるならどうしてこのような結果になったのか教えていただけたらな と思います。よろしくお願いします。

  • 共用体のサンプルコード : 内容がわかりません

    #include <iostream> using namespace std; union bits{ bits(double n); void show_bits(); double d; unsigned char c[sizeof(double)]; }; bits::bits(double n) { d = n; } void bits::show_bits() { int i, j; for(j = sizeof(double)-1; j>=0; j--){ cout << "バイト単位のビットパターン" << j << ":"; for(i=128; i ; i >>=1) if(i &c[j]) cout <<"1"; else cout << "0"; cout <<endl; } } int main () { bits ob(1991.829); ob.show_bits(); return 0; } このコードが何をしているのか解説していただけないでしょうか?

  • ビット列を走査するプログラムの関数化

    char型の変数に0or1を入れて擬似的にビット列にした配列をLSBからMSBまで走査し、一致したらループを抜け終了するプログラムをCで書きたいと思っています。 他のプログラムでも使いまわし、かつ見やすくするためにこの部分を関数化したいのです。ソースにはbreakを使っているのですが、当然ながらbreakはforかwhile内で使わないとダメだと思いますが、ソース作成の都合上、for文は関数内に入れたくないのです。 (つまり、条件分岐を関数化したものをfor文内で用いたい) うまい方法が思いつかずに困っています。もし良い方法をお気づきの方がおられたらご助力下さい。 //===============================================// //=================以下ソース====================// //===============================================// //ビット配列correct_ciphertextとPbinを比較するプログラム //LSBからMSBまで順に走査を行い、違うビットが出てきた時点でbreakし、走査を止める //Pbinは固定値を与えている #include <stdio.h> #include <string.h> unsigned int mes[2]; unsigned int key[2]; char Pbin[64]; char Kbin[64]; char ciphertext[64] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}; void ConvertPtextToBin_ForHost(unsigned int mes[]){ unsigned int tmp_mes[2] = {mes[0], mes[1]}; int i, j; for(j=0;j<=1;j++){ for(i=0;i<=31;i++){ Pbin[j*32 + 31-i] = tmp_mes[j] % 2; tmp_mes[j] = tmp_mes[j] / 2; } } } int main(int argc, char *argv[]){ //initialize mes[0] = 0x00000000; mes[1] = 0x00000000; int i, j, k; int x=0, y=0; while(1){ printf("mes[1] = %d\n", mes[1]); ConvertPtextToBin_ForHost(mes); for(i=0; i<64; i++){ printf("%d", Pbin[i]); if((i+1)%8 == 0) printf(" "); } printf("\n"); //************************* //ビット走査 //************************* for(k=0; k<64; k++){ if( (ciphertext[63-k] == Pbin[63-k]) ){ //同じビットであれば、次のビットを走査する }else{ printf("Error\n");//後ろから走査していって、1ビットでも違うものがあれば違うビット列と判断する break; } } //ここに来たら違うビット列だったということ if(k != 64){ mes[1]++; printf("Not match ciphertext... %dth bit didn't match. (0bit:LSB)\n", k); printf("This was %d*%dth Search...\n\n", y, x); x++; if(x>=65535){i=0; y++;} }else{ //k=64つまり、最後のビットまで同じビットだったということ⇒つまり、「発見」 printf("Match ciphertext\n"); printf("This was %d*%dth Search...\n\n", y, x); break; } //*********************** //ビット走査の終了 //*********************** } }

  • Cの共用体を使ったローテートについて

    独習Cで独学中です。 Cでローテート関数を作る下記の模範解答があり、動作も確認済みですが、どうしてそうなるのかイマイチ理解できません。 教えてください。 ========ここから=================================== #include <stdio.h> void rotate(unsigned char *c); int main(void) { unsigned char ch; int i; ch = 1; for(i=0; i<16; i++) { rotate(&ch); printf("%u\n", ch); } return 0; } void rotate(unsigned char *c) { union { unsigned char ch[2]; unsigned u; } rot; rot.u = 0; /* 16ビットをクリア */ ---(1) rot.ch[0] = *c;          ---(2)  /* 整数を左にシフト */ rot.u = rot.u << 1;        ---(3) /* ビットがc[1]にシフトしたかどうか確認する。 シフトしていれば、OR演算を実行して他方の端に戻る */ if(rot.ch[1]) rot.ch[0] = rot.ch[0] | 1; *c = rot.ch[0]; } ========ここまで============================== 私の考えでは (1)のときにビットの状態は 0000 0000 0000 0000 (2)により ch[0]にchの値が渡されるので 0000 0001 0000 0000 <-ch[0]->|<-ch[1]-> (3)で左に1シフトされると 0000 0010 0000 0000 となり、i=1のときch[0]が2、以後インクリメントごとに4,8,・・・,128まではわかります。 その後、ビットからはみ出した1が最下位に戻ってくるところがよくわかりません。 コメント行の「c[1]」はビット番号のことではなくてch[1]の間違いなのか? だとしてもif文のch[1]は0ではないか???と悩んでます。 解説をどうかよろしくお願いします!

  • 関数でファイルハンドルを読み込む

    このソースファイル'pro1-1.cと名前をつけています)の中の改行を数えるプログラムを作成しています。 main関数でファイルを開き、County関数で数をカウントし、Countx関数で改行の数を表示させる感じで作成しているのですが、County関数での数のカウントの部分で引っかかっています。 途中までできているソースは以下の通りです。 #include <stdio.h> int count[95]={0}; void Countx(void){ int x; for(x=0;x<=95;x++){ if(count[x]!=0){ printf("'%c': %d\n",x+32,count[x]); } } } void County(FILE *fh){ int c; int i; for(c=0;c<=2000;c++){ if(count[c]<32 || count[c]>126){ printf("文字コードエラー\n"); break; while((i=getc(fh))!=EOF){ if(c=='\n'){ count[fh[c]-32]++; } } } } } int main(void){ FILE* fh; if((input=fopen("pro1-1.c","r"))==NULL){ fprintf(stderr,"ファイルが開けません\n"); return 1; } County(fh); Countx(); fclose(fh); return 0; } イメージとしては "\n":○ ←改行の数が入る と言った表示を目指しています。 どなたか正しい解決方法を教えていただけないでしょうか、よろしくお願いします。

専門家に質問してみよう