質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.48%

  • C

    3830questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

範囲指定のビットの変換について

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 443

nonbirikame

score 32

前提

c言語の勉強中の高校生です。書籍で勉強しているのですが、演習問題の答え等がないため質問することが多数あると思いますが、どうかよろしくお願いします。

問題

符号なし整数xの第posビットから第pos + n- 1ビットまでのn個のビットを、1にした値を返す関数set_n,0にした値を返す関数reset_n,反転した値を返す関数inverse_nを作成せよ。

unsigned set_n(unsigned x, int pos, int n){/*...*/}
unsigned reset_n(unsigned x, int pos, int n){/*...*/}
unsigned inverse_n(unsigned x, int pos, int n){/*...*/}

該当のソースコード

unsigned set_n (unsigned x, int pos, int n){
    int y = 0;  //第posビットから pos + n - 1ビットまで1のビット
    int i = 1U;
    int t;
    if(pos != 0){
        for(t = 0; t < pos + n - 1; t++){
            i <<= pos + t;
            y = y | i;
            i = 1U;
        }
    }else{
        for(t = 0; t < n; t++){
            i <<= t;
            y = y | i;
            i = 1U;
        }
    }

    return x | y;
}


unsigned reset_n(unsigned x, int pos, int n){
    int y = 0;  //第posビットから pos + n - 1ビットまで1のビット
    int i = 1U;
    int t;
    if(pos != 0){
        for(t = 0; t < pos + n - 1; t++){
            i <<= pos + t;
            y = y | i;
            i = 1U;
        }
    }else{
        for(t = 0; t < n; t++){
            i <<= t;
            y = y | i;
            i = 1U;
        }
    }

    if(x & y){
        return x ^ y;
    }else{
        return x;
    }
}

疑問点

関数set_nは正常に動作したのですが、関数reset_nは動作が不安定です。
特に第0ビットから始めようとすると意図しない結果が出てしまいます。
そのため、このコードのどこが間違っているのかを知りたいです。

また、関数inverse_nは、分からないため具体的なコードを教えていただきたいです。

補足情報

書籍:新明解©言語 入門編
演習7-5

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Stripe

    2017/09/09 21:34

    set_n()のコードも掲載してください。set_n()が出来れば、reset_n()やinverse_n()も出来るはずなんですが。

    キャンセル

回答 1

checkベストアンサー

+1

こんにちは。

解説するより答えを示した方が早そうなので。

#include <stdio.h>

unsigned make_mask(int pos, int n)
{
    unsigned ret=0;
    for (int i=pos; i < (pos+n); ++i)
        ret |= (1<<i);
    return ret;
}

unsigned set_n(unsigned x, int pos, int n)
{
    unsigned mask = make_mask(pos, n);
    return (x | mask);
}

unsigned reset_n(unsigned x, int pos, int n)
{
    unsigned mask = make_mask(pos, n);
    return (x & ~mask);
}

unsigned inverse_n(unsigned x, int pos, int n)
{
    unsigned mask = make_mask(pos, n);
    return (x ^ mask);
}

int main()
{
    unsigned x=0x1234;
    int pos=4;
    int n=4;
    printf("set_n    =0x%x\n", set_n(x, pos, n));
    printf("reset_n  =0x%x\n", reset_n(x, pos, n));
    printf("inverse_n=0x%x\n", inverse_n(x, pos, n));

    return 0;
}

指定ビットをリセットするには「リセットしたいビットが1の数値」を反転して論理積をとれば良いです。

^排他的論理和です。
0と排他的論理和を取った時は元のビットが変化しませんが、1と排他的論理和を取ると元のビットが反転します。

頑張ってください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/09 21:56

    ということは、
    関数make_maskは自分にとって

    int y = 0; //第posビットから pos + n - 1ビットまで1のビット
    int i = 1U;
    int t;
    if(pos != 0){
    for(t = 0; t < pos + n - 1; t++){
    i <<= pos + t;
    y = y | i;
    i = 1U;
    }
    }else{
    for(t = 0; t < n; t++){
    i <<= t;
    y = y | i;
    i = 1U;
    }
    }

    にあたる、ということですか?
    また、この問題の解釈として第posビットに0を代入して、第nビットに1を代入すると
    最下位ビットのみが1のビットができると言う事なのでしょうか。

    キャンセル

  • 2017/09/09 22:25 編集

    > にあたる、ということですか?

    構造的にはその通りと思います。
    make_maskは、第posビットから第pos + n- 1ビットまでが1で、その他のビットが0の符号なし整数を作っています。

    > また、この問題の解釈として第posビットに0を代入して、第nビットに1を代入すると
    最下位ビットのみが1のビットができると言う事なのでしょうか。

    意味が分かりません。「最下位ビットのみが1のビット」って何の話でしょうか?
    問題文を見る限り、最下位ビットを特別扱いする条件はないように見えます。

    実は、nonbirikameさんのソースは良く見ていません。他の人のソースを読むのは意外に根性が必要なのですよ。
    今回の場合、定形問題なので答えを示した方が楽なので、申し訳ないのですが答えを提示しました。
    何が間違っていたのかnonbirikameさんご自身で発見されることを期待しています。
    頑張ってください。

    キャンセル

  • 2017/09/09 22:39

    ありがとうございます!
    少々変な質問をしてすみませんでした。(その質問については、自己解決したので大丈夫です)
    これからもしっかりと勉強していきます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 受付中

    C:大きな数の計算方法,オーバーフロー回避

    C言語で3^80の計算をしたいのですが、数が大きすぎてオーバーフローしてしまいます。各桁ごとに配列を置けばいいのかとも思いましたが、いまいちよくわかりません。 解決方法が分かる方

  • 解決済

    配列の要素間の和を全パターン求めるプログラムを作成したい。

    皆様ありがとうございました。 前提・実現したいこと <CもしくはC++> 配列の要素間の和を全パターン求めるプログラムを作成したい。 【例】 /*-------------

  • 解決済

    リストの情報を他のクラスに渡す

    前提・実現したいこと 随時更新されていくリストの情報を他のクラスに渡したい 発生している問題・エラーメッセージ 今現在三目並べのプログラムを作っていますが、盤の情報を se

  • 解決済

    Unity: instantateで複製されるprefabの名前を変更したい

    前提・実現したいこと instantateで複製される際にコピーの名前をhoge0 hoge1...hoge5などのように変更し、かつ 一定の数値を超えるとまた0に戻るようなプログ

  • 解決済

    ビットの回転について

    前提 現在書籍でc言語を学習している者です。 その書籍の演習問題は解答が存在しておらず(著者の意図的に) 学習を進めることが困難な時があるので、問題のヒント等を教えていただきたいで

  • 解決済

    gcry_mpi_t 内の公開鍵をビット列で取り出したい

     gcry_mpi_t 内の公開鍵をビット列で取り出したい libgcrypt1.7.6 を使ってRSA暗号をいじってく中で, gcry_mpi_t型におさまっている公開鍵をビット

  • 解決済

    ビットベクトルについて

    C言語初心者です。ビットベクトルを勉強しています。 [0,1,0,0,0,0,1,0,1,...]のような0と1が並んだデータ構造があるとします。 もし、32ビットの領域があれば、

  • 解決済

    python3で大小関係を考慮した順列の作り方

     分からない事 以下のように例えば4個(2N個)の数字が与えられたとして 左側と右側、両方とも必ず数字を小さい順に並びかえたいときの方法が分かりません。 12 34 13 24

同じタグがついた質問を見る

  • C

    3830questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。