第15章 位操作

位操作的方式有兩種: 一種是位運(yùn)算符埠居。一種是位字段

位運(yùn)算符

  1. 二進(jìn)制反碼或按位取反: ~
    運(yùn)算符將1變?yōu)?,0 變?yōu)?
    ~(10011010) //表達(dá)式
    (01100101) //結(jié)果值
#include <stdio.h>

int main(void)
{
  unsigned char val = 2;
  unsigned  char newval;
  newval = ~val;
  printf(" %d \n", val);    //注意該操作并不會(huì)改變原val的值
  printf(" %d \n", newval);

  return 0;
}

  1. 按位與: &
    逐位對比兩個(gè)運(yùn)算對象持隧,生成一個(gè)新值碑隆。對于每個(gè)位瞬内,只有都為1時(shí)結(jié)果才為1
    (10010011) & (00111101)
    (00010001) //結(jié)果
    C提供運(yùn)算符: &=
    val &= 0377;
    val = val & 0377;
    這兩個(gè)相等

  2. 按位或: |
    逐位對比兩個(gè)運(yùn)算對象厘贼,生成一個(gè)新值颂龙。對于每個(gè)位,只要有一位是一就都是一
    (10010011) | (00111101)
    (10111111) //結(jié)果
    C提供運(yùn)算符: |=
    val |= 0377;
    val = val | 0377;
    這兩個(gè)相等

  3. 按位異或: ^
    逐位對比兩個(gè)運(yùn)算對象攒霹,對于每個(gè)位,如果兩個(gè)運(yùn)算對象中相應(yīng)的位一個(gè)為1(但不是兩個(gè)位1)浆洗,結(jié)果為1(簡單來說就是,這兩個(gè)位必須不相同)
    (10010011) ^ (00111101)
    (10101110) //結(jié)果
    C提供運(yùn)算符: ^=
    val ^= 0377;
    val = val ^ 0377;

移位運(yùn)算符

  1. 左移: <<
    將其左側(cè)運(yùn)算對象每一位的值向左移動(dòng)其右側(cè)運(yùn)算符對象指定的位數(shù)集峦,左側(cè)運(yùn)算對象移出左末端位的值丟失伏社,用0填充空出的位置
    (10001010) << 2
    (00101000) //結(jié)果值
  2. 右移: >>
    對于無符號(hào)類型與左移一樣抠刺,對于有符號(hào)類型,其結(jié)果取決于機(jī)器摘昌∷傺空出的位置可用0填充,或用符號(hào)位(即聪黎,最左端的位)的副本填充:

位字段

操作位的第二種方法是位字段罕容。位字段是一個(gè)signed int 或unsigned int變量中的一組相鄰的位

struct box_props
{
    bool opaque                     : 1;
    unsigned int fill_color         : 3;
    unsigned int                    : 4;
    bool show_border                : 1;
    unsigned int border_color       : 3;
    unsigned int border_style       : 2;
    unsigned int                    : 2;
};

1

/**
 * 編寫一個(gè)函數(shù),把二進(jìn)制字符串轉(zhuǎn)換為一個(gè)數(shù)值稿饰。例如,有下面語句:
 * char * pbin = "01001001"
 * 那么把pbin作為參數(shù)傳遞給該函數(shù)后锦秒,他應(yīng)該返回一個(gè)int類型的值25
*/

#include <stdio.h>
#include <math.h>
#include <string.h>

int twototen(const char * ps);

int main(void)
{
    int num;
    char * pbin = "01001001";
    num = twototen(pbin);
    printf("%d", num);
    return 0;
}

int twototen(const char * ps)
{
    int val = 0;
    while (*ps != '\0')
    {
        val = 2 * val + (*ps++ - '0');
    }
    return val;
}

2

/**
 * 編寫一個(gè)程序, 通過命令行參數(shù)讀取兩個(gè)二進(jìn)制字符串喉镰,對這兩個(gè)二進(jìn)制數(shù)使用~運(yùn)算符旅择、&
 * 運(yùn)算符、|運(yùn)算符和^運(yùn)算符侣姆,并以二進(jìn)制字符串形式打印結(jié)果
*/

#include <stdio.h>
#include <limits.h>

int twototen(const char *);
char * itobs(int , char *);

int main(int argc, char const *argv[])
{
    int n1, n2;
    char bran[CHAR_BIT * sizeof(int) + 1];

    n1 = twototen(argv[1]);
    n2 = twototen(argv[2]);

    printf("~%s : %s\n", argv[1], itobs(~n1, bran));
    printf("~%s : %s\n", argv[2], itobs(~n2, bran));
    printf("&運(yùn)算: %s\n", itobs((n1&n2), bran));
    printf("|運(yùn)算: %s\n", itobs((n1|n2), bran));
    printf("^運(yùn)算: %s\n", itobs((n1^n2), bran));
    return 0;
}

int twototen(const char *str)
{
    int n = 0;
    
    while (*str)
    {
        n = 2 * n + (*str++ - '0');
    }
    return n;
}

char * itobs(int n, char *str)
{
    int i;
    const static int size = CHAR_BIT * sizeof(int);

    for ( i = size - 1; i >= 0; i--, n >>= 1)
    {
        str[i] = (01 & n) + '0';
    }
    str[size] = '\0';
    return str;
}

3

/**
 * 編寫一個(gè)函數(shù)生真,接受一個(gè)int類型的參數(shù),并返回該參數(shù)中打開位的數(shù)量捺宗。在一個(gè)程序中測試該函數(shù)
*/

#include <stdio.h>
#include <limits.h>

int on_off(int n);

int main(void)
{
    int num;
    int i;

    puts("Please enter num");
    scanf("%d", &i);
    num = on_off(i);
    printf("%d", num);
    return 0;
}

int on_off(int n)
{
    int count = 0;
    int i;
    const static int size = CHAR_BIT * sizeof(i);
    
    for ( i = 0; i < size; i++, n >>= 1)
    {
        if (n & 01)
        {
            count++;
        }
    }
    return count;
}

4

/**
 * 編寫一個(gè)程序柱蟀,接受兩個(gè)int類型的參數(shù): 一個(gè)是值;一個(gè)是位的位置。如果指定
 * 的位置為1蚜厉,該函數(shù)返回1;否則返回0.在一個(gè)程序中測試該函數(shù)
*/

#include <stdio.h>
#include <limits.h>

int localtion(int, int);

int main(void)
{
    int value, num;
    int result;
    puts("Please enter values");
    scanf("%d", &value);
    puts("Please enter numbers");
    scanf("%d", &num);
    result = localtion(value, num);
    printf("%d", result);

    return 0;
}

int localtion(int value, int num)
{
    value >>= (num-1);
    if (value & 1)
    {
        return 1;
  }
    return 0;    
}

5

/**
 * 編寫一個(gè)函數(shù)长已,把一個(gè)unsigned int 類型值中的所有位向左旋轉(zhuǎn)指定數(shù)量的位。例如
 * rotate_l(x, 4)把x中所有位同左移4個(gè)位置弯囊,而且從最左端移出的位會(huì)重寫出現(xiàn)在右端
 * 也就是說痰哨,把高階位移出的位放入低階位。在一個(gè)程序中測試該函數(shù)
*/

#include <stdio.h>

void rotate_l(int x, int n);

int main(void)
{
    unsigned int num;
    unsigned int n;
    puts("Please enter num");       //要被移動(dòng)的數(shù)字
    scanf("%u", &num);
    puts("Please enter nums");    //移動(dòng)位數(shù)
    scanf("%u", &n);
    rotate_l(num, n);
    return 0;
}

void rotate_l(int x, int n)
{
    unsigned int val;
    val = x >> (32 - n);
    x <<= n;
    x |= val;
    printf("%u", x);
}

6

/**
 * 設(shè)計(jì)一個(gè)位字段結(jié)構(gòu)以存儲(chǔ)下面的信息.
*/
#include <stdio.h>
#include <stdbool.h>
struct set_word
{
    unsigned int typeface       : 8;
    unsigned int bigorsmall     : 7;
    unsigned int                : 1;    //作為間隙
    unsigned int aline          : 3;
    unsigned int                : 1;
    bool bold                   : 1;
    bool italic                 : 1;
    bool underline              : 1;
    unsigned int                : 1;
};

const char * italics[8] = {"left", "middle", "right"};  //等會(huì)打印用到
const char * on_off[3] = {"off", "on"};

void show_news(struct set_word * pst);      //展示字體信息
char menu(void);            //展示菜單選項(xiàng)
char get_ch(void);          //讀取選項(xiàng)的函數(shù)
void chang_font(struct set_word * pst);     //改變字體
void chang_size(struct set_word * pst);     //改變大小
void chang_alignment(struct set_word * pst);    //對齊方式
void change_italic(struct set_word * pst);      //是否斜體
void change_bold(struct set_word * pst);        //是否實(shí)線
void change_under(struct set_word * pst);       //有沒有下劃線

int main(void)
{
    char ch;
    struct set_word sets = {
        1, 12, 0, 0, 0, 0
    };
    show_news(&sets);
    while ((ch = menu()) != 'q')
    {
        switch (ch)
        {
        case 'f':
            chang_font(&sets);
            break;
        case 's':
            chang_size(&sets);
            break;
        case 'a':
            chang_alignment(&sets);
            break;
        case 'b':
            change_bold(&sets);
            break;
        case 'i':
            change_italic(&sets);
            break;
        case 'u':
            change_under(&sets);
            break;
        default:
            puts("Error!");
            break;
        }
        show_news(&sets);
    }
    
    show_news(&sets);
    return 0;
}

void show_news(struct set_word * pst)
{
    puts("ID    SIZE    ALIGNMENT    B       I       U");
    printf("%-8d%-8d%-8s  %-8s%-8s%-8s\n", pst->typeface,
    pst->bigorsmall, italics[pst->aline], on_off[pst->bold], on_off[pst->italic],
    on_off[pst->underline]);
}

char menu(void)
{   
    char ch;-
    puts("f)change font    s)change size    a)change alignment");
    puts("b)toggle bold    i)toggle italic  u)toggle underline");
    puts("q)quit");
    ch = get_ch();
    return ch;
}

char get_ch(void)
{
    char ch;
    scanf("%c", &ch);
    while (getchar() != '\n')
        continue;
    return ch;
}

void chang_size(struct set_word * pst)
{
    unsigned int n;
    scanf("%u", &n);
    while (getchar() != '\n')
        continue;
    if (n > 127)
    {
        n &= 127;    //二進(jìn)制是1111111
    }
    
    pst->bigorsmall = n;

}

void chang_alignment(struct set_word * pst)
{
    char ch;
    puts("Select alignment:");
    puts("1)left   c)center    r)right");
    scanf("%c", &ch);
    while (getchar() != '\n')
        continue;
    switch (ch)
    {
    case 'l':
        pst->aline = 0;
        break;
    case 'c':
        pst->aline = 1;
        break;
    case 'r':
        pst->aline = 2;
        break;
    
    default:
        puts("Errorrrr!");
        break;
    }
}

void change_italic(struct set_word * pst)
{
    if (pst->italic == 0)
    {
        pst->italic = 1;
    }
    else
    {
        pst->italic = 0;
    }   
}

void change_bold(struct set_word * pst)
{
    if (pst->bold == 0)
    {
        pst->bold = 1;
    }
    else
    {
        pst->bold = 0;
    }   
}
void change_under(struct set_word * pst)
{
    if (pst->underline == 0)
    {
        pst->underline = 1;
    }
    else
    {
        pst->underline = 0;
    }   
}

void chang_font(struct set_word * pst)
{
    unsigned int n;
    scanf("%u", &n);
    while (getchar() != '\n')
        continue;
    if (n > 255)
    {
        n &= 255;    //二進(jìn)制是1111111
    }
    
    pst->typeface = n;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末匾嘱,一起剝皮案震驚了整個(gè)濱河市斤斧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌霎烙,老刑警劉巖撬讽,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異悬垃,居然都是意外死亡游昼,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進(jìn)店門尝蠕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烘豌,“玉大人,你說我怎么就攤上這事看彼±扰澹” “怎么了囚聚?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長标锄。 經(jīng)常有香客問我顽铸,道長,這世上最難降的妖魔是什么料皇? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任谓松,我火速辦了婚禮,結(jié)果婚禮上践剂,老公的妹妹穿的比我還像新娘鬼譬。我一直安慰自己,他們只是感情好舷手,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布拧簸。 她就那樣靜靜地躺著,像睡著了一般男窟。 火紅的嫁衣襯著肌膚如雪盆赤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天歉眷,我揣著相機(jī)與錄音牺六,去河邊找鬼。 笑死汗捡,一個(gè)胖子當(dāng)著我的面吹牛淑际,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播扇住,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼春缕,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了艘蹋?” 一聲冷哼從身側(cè)響起锄贼,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎女阀,沒想到半個(gè)月后宅荤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡浸策,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年冯键,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片庸汗。...
    茶點(diǎn)故事閱讀 39,919評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡惫确,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情雕薪,我是刑警寧澤昧诱,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站所袁,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏凶掰。R本人自食惡果不足惜燥爷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望懦窘。 院中可真熱鬧前翎,春花似錦、人聲如沸畅涂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽午衰。三九已至立宜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間臊岸,已是汗流浹背橙数。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留帅戒,地道東北人灯帮。 一個(gè)月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像逻住,于是被迫代替她去往敵國和親钟哥。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容