• ベストアンサー

ビットをローテートするプログラムの解説をお願いします。(C言語)

下記のプログラムは、rotate() を呼び出されるたびに1つずつ左にビットをローテートするものです。 #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ビットをクリア */ rot.ch[0] = *c; /* 整数を左にシフト */ rot.u = rot.u << 1; /* ビットがc[1]にシフトしたかどうか確認する。 シフトしていれば、OR演算を実行して他方の端に戻る */ if(rot.ch[1]) rot.ch[0] = rot.ch[0] | 1; *c = rot.ch[0]; } 【質問】 自分で考えてみたので、間違いがあれば、ご指摘お願いします。 --------------------------------------------------------- ch = 1; だから rotate(&ch); で初回実行時に *c に1を渡す。 i=0 のとき、 rot.ch[0]  rot.ch[1] 0000 0000  0000 0000    rot.u = 0;     rot.u 0000 0001  0000 0000    rot.ch[0] = *c; *c は 1 0000 0010  0000 0000    rot.u = rot.u << 1; if(rot.ch[1]) → 偽 *c = rot.ch[0]; で *c が 0000 0010 すなわち 2 になる。 printf文で「2」を表示。 --------------------------------------------------------- i=1 のとき、 rot.ch[0]  rot.ch[1] 0000 0000  0000 0000    rot.u = 0;     rot.u 0000 0010  0000 0000    rot.ch[0] = *c; *c は 2 0000 0100  0000 0000    rot.u = rot.u << 1; if(rot.ch[1]) → 偽 *c = rot.ch[0]; で *c が 0000 0100 すなわち 4 になる。 printf文で「4」を表示。 --------------------------------------------------------- i=2 のとき、rot.ch[0] が 0000 1000 で *c が 8 になる。 printf文で「8」を表示。 i=3 のとき、rot.ch[0] が 0001 0000 で *c が 16 になる。 printf文で「16」を表示。 i=4 のとき、rot.ch[0] が 0010 0000 で *c が 32 になる。 printf文で「32」を表示。 i=5 のとき、rot.ch[0] が 0100 0000 で *c が 64 になる。 printf文で「64」を表示。 i=6 のとき、rot.ch[0] が 1000 0000 で *c が 128 になる。 printf文で「128」を表示。 --------------------------------------------------------- i=7 のとき、 【ここからがどうしても分かりません。どうか力をかして頂けないでしょうか?お願いします。】

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

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.7

★回答者 No.1 です。 >ただ、わかりやすく並び替えただけですね!  ↑  はい、その通りです。  一般に配列は左から右に配置するイメージで考えますが、場合によっては逆の右から左に  配置するイメージで考えることもあります。この場合は配列の処理内容によって変わります。 ・今回は共用体のお勉強ですよね。  去年も全く同じ質問がありました。  共用体を使ってローテーションするもので何かの本に載っているのですよね。  普通、1バイトのビットのローテーションは回答者No.5(jacta)さんのように記述します。  今回は共用体の仕組みを理解するためのローテーションにも使えると本に書かれていただけです。  実際にはエンディアンが絡んでくるので共用体よりもビットシフト、ビットORを組み合わせます。 ・ちなみに共用体を使えばlong型の上位16ビット、下位16ビットを取り出すことも可能です。    共用体を次のようにします。  union {   unsigned short s[ 2 ];   unsigned long v;  } x;    x.v = 0x12345678;…代入  x.s[0]=0x5678…下位16ビット  x.s[1]=0x1234…上位16ビット  となります。   ・また、構造体と組み合わせるともっと分かりやすくなります。  union {   struct {    unsigned short lo;    unsigned short hi;   } s;   unsigned long v;  } x;    x.v = 0x12345678;…代入  x.s.lo=0x5678…下位16ビット  x.s.hi=0x1234…上位16ビット  となります。 まとめ: ・リトル・エンディアンでは  union {   struct {    unsigned char a;…下位ビット    unsigned char b;    unsigned char c;    unsigned char d;…上位ビット   } s;   unsigned long v;  } x;    x.v=0x12345678;  x.s.a=0x78  x.s.b=0x56  x.s.c=0x34  x.s.d=0x12  となります。 ・以上。

Guchiken
質問者

お礼

2度も回答ありがとうございます! 検索したら、同じ質問をしている人がいました。 もう少し、調べてから質問した方が良かったのかもしれません。ごめんなさい! 質問したローテーションするプログラムは『独習C 第3版』に記載されているものです。 コードのサンプル、今後の参考にさせて頂きます!! いろいろ勉強になりました!! 回答本当にありがとうございました。

その他の回答 (6)

  • nak777r
  • ベストアンサー率36% (49/136)
回答No.6

>int型はIntel系CPUを意識して、「16または32」としたんでしょうか? int と Intel系はまったく関係ありません short は short int の略で、2byte の整数 long は long int の略で、4byte の整数 int は、short int 又は long int の略された部分の文字で、 integer の略、和訳すると単なる「整数」の意味になります ですので、int と記述した場合、short int と解釈するのか、 long int と解釈するのかは、コンパイラによるわけです 通常は、コンピュータの演算が楽な方を、コンパイラを作成 しているメーカーが採用していたので、DOSの時代(8bit、 16 bit CPU主流の時代)は、int = short 解釈が多かったの ですが 32bit CPUが主流の現在では、逆に long の方が処理しやすい為、 int = long 解釈のコンパイラが多くなってます

Guchiken
質問者

お礼

疑問に対する回答ありがとうございます!! int は、short int 又は long int の略された部分の文字なんですね! そしてコンパイラによってintの長さが決まるから「16または32」なんですね! 勉強に使っている本を読み直したら、 「short intはintより短く、long intはintより長くなるのが普通です。たとえば、ほとんどの16ビット環境では、intは16ビット長で、long intは32ビット長です。ただし、longとshortの厳密な意味は処理系に依存します。(中略)。事実、ほとんどの16ビット環境では、intもshort intも同じサイズとして扱われます。さらに、多くの32ビット環境ではintとlong intのサイズが同じです。」 と記載されていました!! 何回も回答本当にありがとうございました。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.5

質問に対する回答というわけではありませんが... なぜ共用体を使ったりして、こんな面倒なことをしなければならないのか謎です。 void rotate(unsigned char *c) {  *c = (unsigned char)(*c << 1 | *c >> (CHAR_BIT - 1)); } で済んでしまうのではないでしょうか? 敢えて分かりにくくしているような気がします。

Guchiken
質問者

お礼

回答ありがとうございます! このプログラムは『独習C 第3版』にシフト演算子の練習問題として載っている、 「Cにはローテート(rotate)演算子はありません。ローテートはシフトに似ていますが、はみ出たビットを逆の端に置きます。(中略)。呼び出されるたびに1つずつ左にローテートするrotate()という関数と、それを利用するプログラムを作成してください。」 という問題の解答の例として載っているものです。 問題文にはヒントとして、 「バイトの端からはみ出たビットにアクセスするには、共用体を使用します。」 とあるため、解答例にも共用体が使用されています。 ご指摘の通り、「CHAR_BIT」を使うために #include <limits.h> を追加して、 void rotate(unsigned char *c) { *c = (unsigned char)(*c << 1 | *c >> (CHAR_BIT - 1)); } とした方が簡単でした!!ありがとうございます!!

  • nak777r
  • ベストアンサー率36% (49/136)
回答No.4

説明が少し不十分だったので補足します short b; と型宣言した場合、プログラムは、メモリ上に2バイト分のメモリ領域を確保します long c; と型宣言した場合、プログラムは、メモリ上に4バイト分のメモリ領域を確保します b=0x1234; と記述した場合、 プログラムは、確保されたメモリに、 [0x34][0x12]と格納します c=0x12345678; と記述した場合、 プログラムは、確保されたメモリに、 [0x78][0x56][0x34][0x12]と格納します 上記の様にメモリに値を保存するのが、リトルエンディアン と呼ばれる方式で Intel系のCPUでは、これを採用しています 逆にビッグエンディアンと呼ばれる方式の場合、 b=0x1234; と記述した場合、[0x12][0x34]と格納します c=0x12345678; と記述した場合、[0x12][0x34][0x56][0x78]と格納します union は同じメモリの領域を参照するので、、、後は先の説明の通りです。

Guchiken
質問者

お礼

補足ありがとうございます!! ちょっと、理解に不安が残っているので、 エンディアンがどういうものなのか自分で調べてみたいと思います。 回答本当にありがとうございました。

  • luckymako
  • ベストアンサー率55% (29/52)
回答No.3

実行している環境がわからないので  int型 2 Byte  char型 1 Byte  リトルエンディアンマシン と仮定します。 ビックエンディアンマシンだと正常に動かないと思われます。 まず union の確認から union は一つの領域を複数名で参照するための物です(共用体)。 よって、提示されたプログラムが正しく動くのであれば u に 1 を代入するとメモリ上には  |ch[0]---|ch[1]---| 名前1  |00000001|00000000| メモリ上のビット列  |u_下位--|u_上位--| 名前2 のように格納されているはずです。 (リトルエンディアンマシンでは上位バイトと下位バイトが逆順になります。) ビット列の遷移を見てみると  |00000001|00000000| 0 回ローテート  |00000010|00000000| 1 回ローテート   ・・・  |01000000|00000000| 6 回ローテート  |10000000|00000000| 7 回ローテート  |00000000|00000001| 8 回ローテート   ↓  |00000001|00000001| 論理和の結果 8 回目のローテートで u の上位バイトつまり ch[1] にビットが立ちます。 7 回目までは  ch[1] = 0 で 8 回目で  ch[1] = 1 となり ch[1] が 非0 なので ifの条件が 真 となり ch[0] と 1 の論理和が ch[0] に代入されます。 rotate は ch[0] の中身のみ ( |00000001| ) を返しているので 8 回目以降は 0 回と同じことの繰り返しになります。 つまり i=7 のとき、rot.ch[0] が 0000 0001 で *c が 1 になる。 printf文で「1」を表示。 i=8 のとき、rot.ch[0] が 0000 0010 で *c が 2 になる。 printf文で「2」を表示。

Guchiken
質問者

お礼

回答ありがとうございます!! リトル・エンディアンマシンでは上位バイトと下位バイトが逆順になるんですか…ややこしいですね… エンディアンについて詳しく載っている書籍とかないものですかね… ちょっと頭がパニックになっています。 回答ありがとうございました。

  • nak777r
  • ベストアンサー率36% (49/136)
回答No.2

union { unsigned char ch[2]; unsigned u; } rot; 問題のプログラムは、int = 16Bit で Intel系のCPUでないと まともに動かないプログラムなので、あまりよいプログラムとは いえないですね 32Bit CPU時代のコンパイラで実行するのなら unsigned u は、unsigned short u に直してください union でくくられた u と ch[0] はメモリ上同じ領域に確保されます Intel系は LOW ワード、HIワードの順に確保されているので、 rot.u = 256; とした場合 rot.ch[0]  rot.ch[1] 0000 0000  0000 0001 となります

Guchiken
質問者

お礼

回答ありがとうございます!! int=16Bit で Intel系のCPUでないとまともに動かないんですか… 私の使っている本には、 [型]        [典型的なビット長] int          16または32 unsigned short int     16 とあるんですが、int型はIntel系CPUを意識して、「16または32」としたんでしょうか? unsigned short int は 16 でちょうどいいですね。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.1

★共用体を理解していないだけです。 >rot.ch[0]  rot.ch[1]  ↑  こう考えるから分かりづらいのです。  書き方を  rot.ch[1]  rot.ch[0]  と書けば分かりやすくなりませんか?  つまり  rot.ch[1] rot.ch[0]  0000 0000 0000 0001 i=0  0000 0000 0000 0010 i=1  0000 0000 0000 0100 i=2  0000 0000 0000 1000 i=3  0000 0000 0001 0000 i=4  0000 0000 0010 0000 i=5  0000 0000 0100 0000 i=6  0000 0000 1000 0000 i=7  0000 0001 0000 0000 i=8 ←注目  ↑  ch[1]にシフトします。  このとき if ( rot.ch[1] )→真 となります。  その後に rot.ch[0] = rot.ch[0] | 1; を演算することでローテーションします。 ・あと共用体を使う場合は処理系によってエンディアンが違うことがあるため注意して下さい。  もしもビッグ・エンディアンだと rot.ch[0] = *c; と代入しても rot.u が 0x0001 とならず  0x0100 になってしまい正しくローテーションで来ません。  処理系がリトル・エンディアンなら正しくローテーションできるでしょうね。 ・以上。

Guchiken
質問者

お礼

回答ありがとうございます!!! ビットの並び(右から左)に対して、配列の並びが左から右だから、逆だったんですね! リトル・エンディアンとビッグ・エンディアンですか… 私のコンピュータはIntelのx86系CPUだからリトル・エンディアンですね? 今後、共用体を使う際には、そのことも頭に入れておきたいと思います。

Guchiken
質問者

補足

お礼の訂正。 >ビットの並び(右から左)に対して、配列の並びが左から右だから、逆だったんですね! 書き方によっては一概に言えないですね(ANo.3の書き方とか)。 ただ、わかりやすく並び替えただけですね!

関連するQ&A

  • 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ではないか???と悩んでます。 解説をどうかよろしくお願いします!

  • C言語のコードについて

    C言語の問題なのですか、作成したのですが内容がわからないです。 コードをわかりやすく解説していただけると嬉しいです。 #include <stdio.h> void printBinary(unsigned char num) { int i ; /*①上位ビットから順に表示する*/ for(i = 7 ; i >= 0; i--) { /*②シフトとマスクを使用しています。*/ printf("%d", (num>>i) &0x01 ); } printf("\n"); } int main(void) { unsigned char num1 = 0xD2;/*11010010*/ unsigned char num2 = 0x5E;/*01011110*/ printf("0xD2 : "); printBinary(num1); printf("0x5E : "); printBinary(num2); return 0; }

  • C言語

    文字列を逆順にするプログラムを考えているのですが分かりません。(例)qwerならrewqです。入力終了は、EOFです。考えたのですが、分かりません。(コンパイルエラーです。)教えてください。宜しくお願いします。#include <stdio.h> unsigned str_length(const char str[]) { unsigned len=0; while (str[len]) len++; return (len); } void put_rstring(const char str[]) { unsigned i = str_length(str): while (i-- >0) putchar(str[i]); } int main(void) { char str[30]; int ch; printf("文字列を入力\n"); /* ----この文字列を入力したあとに、Ctrl+Zを押すと、逆から表示               で反対から、文字列が表示----*/ while (1) { ch=getchar(); if (ch==EOF) break; } printf("逆から表示"); put_rstring(str); puts("です。"); return(0); }

  • C言語のビットシフトの質問

    C言語の右ビットシフトで、以下のプログラムの結果について、納得できずにいます。 dを右にシフトすると、上位ビットには0が入るのではないでしょうか? よろしくお願いします。 プログラム unsigned char d='0'; printf("%c\n", d); printf("%c\n", d>>5); 結果 0 『

  • C言語

    入力した文字列と文字列'x'を受け取り、'x'の位置のポインタを返すのですが、例えば、saxcvと入力すると、xcvと表示されるのですが、このソースだと、saxcvと全部表示されてしまいます。分からないので、教えてください。宜しくお願いします。 #include <stdio.h> char *a(char *sew) { char *p=sew; while (*sew != 'x') { sew++; } return(p); } int main(void) { char str[21] ={'\0'}; int i=0,no=0; char ch; printf("文字を入力してください:"); while (i<21) { ch=getchar(); if (ch=='\n') {break;} else if (ch != '\0' && ch != '\0') { str[i] =ch; i++; } } for(i=0; i<20; i++) { if(str[i]=='x') { printf("'x'以降は%sです。\n", a(str)); no=1; break; } } if (no==0) printf("'x'は見つかりませんでした。"); 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言語)

    下記のプログラムはビットごとのANDを使って、 キーボードから入力された文字のASCIIコードをバイナリ表記で表示します。 #include <stdio.h> #include <conio.h> int main(void) { char ch; int i; printf("文字を入力してください: "); ch = getche(); printf("\n"); /* バイナリ表記を表示する */ for(i=128; i>0; i=i/2) if(i & ch) printf("1 "); else printf("0 "); return 0; } 【質問】 「バイナリ表記を表示する」部分のコードで、 1バイト(8bit)の最上位ビットは128(2の7乗)の重みがあり、それを初期値に与えて、 「i=i/2」で64,32,16,8,4,2,1と重みが下がっていくというのは分かりますが、 if(i & ch) で、どうして「i & ch」とすることで、バイナリ表記が表示できるのでしょうか? どなたか教えて頂けないでしょうか?お願いします。

  • C言語計算プログラム

    Cの計算プログラム 下のプログラムを (1)上位桁の不要な0を表示しない (2)3つの数を計算できるようにする (3)0が入力されるまでは入力を受け付けて加算を繰り返す プログラムに改造する方法を教えてください。 #include <stdio.h> #define MAXDIGIT 70 void reset(char*,int); void input(char*,int); void add(char*,char*,char*,int); void add_digit(char ,char ,char ,char* ,char* ); void display(char* ,char* ,char* ,int ); void lineprint(char ,char* ,int ); void linedraw(char ,int ); int main(void) { char a[MAXDIGIT],b[MAXDIGIT],c[MAXDIGIT]; reset(a,MAXDIGIT); reset(b,MAXDIGIT); reset(c,MAXDIGIT); input(a,MAXDIGIT); input(b,MAXDIGIT); add(a,b,c,MAXDIGIT); display(a,b,c,MAXDIGIT); return 0;} void reset(char* buf,int maxdigit) { int i; for(i=0;i<maxdigit;i++) buf[i]=0; return;} void input(char* buf,int maxdigit) { char str[MAXDIGIT]; int i,j; printf("input data:"); scanf("%s",str); i=0; while(str[i]!='\0') i++; j=0; while(i>0){ buf[j]=str[i-1]-'0'; j++; i--; } return;} void add(char* a,char* b,char* c,int maxdigit) { int i; char carry_in,carry_out; i=0; carry_in=0; while(i<maxdigit) { add_digit(a[i],b[i],carry_in,&c[i],&carry_out); carry_in=carry_out; i++;} return;} void add_digit(char a,char b,char carry_in,char* c,char* carry_out) { *c=(a+b+carry_in)%10; *carry_out=(a+b+carry_in)/10; return;} void display(char* a,char* b,char* c,int maxdigit) { lineprint(' ',a,maxdigit); lineprint('+',b,maxdigit); linedraw('-',maxdigit+1); lineprint(' ',c,maxdigit); return;} void lineprint(char c,char* line,int maxdigit) { int i,maxdigitlimit; maxdigitlimit=maxdigit-1; printf("%c",c); for(i=maxdigitlimit;i>=0;i--){ printf("%1d",line[i]); } printf("\n"); return;} void linedraw(char c,int length) { int i; for(i=0;i<length;i++) printf("%c",c); printf("\n"); return;}

  • 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型ビット構成の表示されるので、自分の考え方が間違えている。なのですが、どう間違えているかがわかりません。 多少説明文の省略しているためわかりにくいかもしれませんが、間違えを指摘していただけないでしょうか?

  • C言語について教えてください。

    #include <ctype.h> #include <stdio.h> void name_toupper(char istr[], char ostr[]) { unsigned i = 0; while (istr[i]) { ostr[i] = toupper(istr[i]); i++; } ostr[i] = '\0'; } void name_tolower(char istr[], char ostr[]) { unsigned i = 0; while (istr[i]) { ostr[i] = tolower(istr[i]); i++; } ostr[i] = '\0'; } void name_change(char istr[], char ostr[]) { unsigned i = 0; while (istr[i]) { if(isupper(istr[i])) { ostr[i] = tolower(istr[i]); } else { ostr[i] = toupper(istr[i]); } i++; } ostr[i] = '\0'; } int main(void) { char buffer[100]; char result[100]; printf("文字"); gets(buffer); name_toupper(buffer,result); printf("大文字: %s\n", result); name_tolower(buffer,result); printf("小文字: %s\n", result); name_change(buffer,result); printf("大小交換: %s\n", result); return 0; } 出力結果 文字abc DEFG 大文字: ABC DEFG 小文字: abc defg 大小交換: ABC defg 上のプログラムで文字関数isupperを用いずにプログラムする方法を教えてもらえませんか? もしくわ、用いずにプログラムすることは不可能ですか? 教えてください。 よろしくお願いします。

専門家に質問してみよう