翁恺C语言基础学习——位运算概念,自定义容器

C语言位运算符

  •   ‘&’ —— 按位与 ,'(x)i == (y)i  ==1  则--> (x & y ) i=1,否则(x & y ) =0 ',也就是两个二进制数两位都都为1时,则为1  ,否则为0

  •    ‘|’  ——按位或 ,   '(x)i=1 或者  (y)i =1 则--> (x | y)i =1'   两个二进制数两位只要有一个不为0,则为1,否则为0

  •    ‘~’ ——按位取反, '~(x)i = 1-(x)i' , 把1位变成 0, 0位变成1   ,

  •         ‘^’—— 按位异或 '(x) i=(y)i 则  (x)i ^ (yi) =0    否则为 1'    任何一个数  用同一个值异或两次,等于原来的自己

  •   '<<'——左移运算   'i << j' 将 'i'中所有的位向左移动'j'个位置, x<<1 == > x *=2     x<< n  ==> x *= 2的‘n’次方, 所有小于int类型的值,移位以int方式来做,结果是int

  •   '>>'——右移运算  ' i>> j' 将 'i'中所有的位向右移动'j'个位置, x>> 1  ==> x /=2 , x>>n ==> x /= 2的'n'次方!所有小于int类型,移位以int方式来做,结果是int,对于 unsigned类型左边填入0,有符合位,则符号位不变

位移不能使用负数 ,未定义的行为

void print_bit(int n);
void print_unsigned_bit(unsigned n);



//按位的与
void test_bit_with_and() {
    //应用一:让某一位或某些位为0 如:x & 0xFE   (0xFE-->1111,1110,进行位运算后这个数的最后一位就为0)
    int a = 33;
    print_bit(a);
    int res = a & 0xFE; //(32-->'0010,0001'  & '1111,1110'  ===> 0010,0000)
    print_bit(res);
    printf("%d
", res);
    //应用二:获取某个数当中的一段: x & 0xFF    (0xFF-- > '1111,1111', 位运算后 得出这个数最后8位的值)
    int data =0xfffe ;
    print_bit(data);    //输出 binary->1111,1111,1111,1110
    data = data & 0xff;    //取后8位
    print_bit(data);    //输出 binary-->1111,1110
}

//按位或 
void test_bit_with_or() {
    //应用一:使得一位,或者几位为 1
    int data = 0xAA;    //binary -->    1010,1010
    int data1 = 0x54;    //binary -->    0101,0100
    data = data | data1;
    print_bit(data);    //binary -->    1111,1110
    //应用二:把两个数拼接起来
    data = 0xff00;        //binary -->111,1111,0000,0000
    data1 = 0x00ff;        //binary -->0000,0000,1111,1111
    data = data | data1;
    print_bit(data);    //binary -->111,1111,1111,1111
}

void test_bit_with_xor() {
    //应用,简单的数据加密,解密
    int data = 0xAA;    //binary -->    1010,1010
    int data1 = 0x54;    //binary -->    0101,0100
    data = data ^ data1;
    data = data ^ data1;
    print_bit(data);    //binary -->    1010,1010
}


/*
    打印二进制数据
*/
void test_mybitprintf(int number) {
    if (number == 0) { 
        printf("binary-->%d", 0); 
        return;
    }
    unsigned int mask = 1u << 31; //int类型4个字节,无符号 左移31位则 1000,0000,0000,0000,0000,0000,0000,0000
    printf("%d-binary===>", number);
    //直到mask 右移32位 得到结果 0 时,for循环退出
    for ( ; mask; mask >>= 1)
    {
        // (1000,0000,0000,0000,0000,0000,0000,0000)  & (0000,0000,0000,0000,0000,0000,0000,0010)  
        // 得出结果===> 0000,0000,0000,0000,0000,0000,0000,0000   非零才为真,直到倒数第二位的'1' 结果=1 输出1 否则输出0
        int temp = number & mask;
        printf("%d", temp ? 1 : 0 );
    }
    printf("
");
}

/*    位段, 常用于单片机特殊寄存器结构,编译器会安排其中位的排列,不可移植性 
          当所需要的位超过一个int(32位)时,使用多个int,直到容纳这个“位段”
          可以用位段的成员名称访问指定数据的第几位,比移位,与,或更直观让人接受
*/
//位段结构体
struct  U0
{
    unsigned int leading : 3;
    unsigned int flag1 : 1;
    unsigned int flag2 : 1;
    int trailing : 27;

};
void testU0(){
    struct U0 uu;
    uu.leading = 2;
    uu.flag1 = 1;
    uu.flag2 = 1;
    uu.trailing = 0;
    printf("sizeof(uu)==%lu
", sizeof(uu));
    int res = *(int*)&uu ;  // 取结构体地址,强转成 int指针,获取它的整形值,单片机常用
    test_mybitprintf(res);    //binary===>00000000000000000000000000011010
}

int main() {
    //test_bit_with_and();
    //test_bit_with_or();
    //test_bit_with_xor();
    //test_mybitprintf(2);
    testU0();
    return 0;
}
位运算小例子

自定义容器——可变数组

头文件

#ifndef __ARRAY_H__
#define __ARRAY_H__

typedef struct
{
    int *array;
    int size;
}Array;

Array array_create(int init_size);                //初始化数组大小
void array_free(Array *a);                        //释放数组空间
int    array_size(const Array *a);                    //返回数组的大小
int* array_at(Array *a, int index);                //获取指定位置的数组内容的指针
void array_inflate(Array *a, int more_size);    //对数组进行扩容
#endif __ARRAY_H__ 

可变数组实现

#define _CRT_SECURE_NO_WARNINGS
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include "array.h"

//typedef struct
//{
//    int *array;
//    int size;
//}Array;

const BLOCK_SIZE = 20;

//初始化数组大小
Array array_create(int init_size)
{
    Array a;
    a.size = init_size; 
    a.array = (int*)malloc(sizeof(int)*  a.size);
    return a;
}
//释放数组空间
void array_free(Array *a) 
{
    free(a->array);
    a->array = NULL;
    a->size = 0;
}
//返回数组的大小,封装的概念,保护size不被直接访问,
int    array_size(const Array *a) 
{
    return a->size;
}
//获取结构的数组指定位置的指针
//返回指针而不是int的意义: 指针既可以获取值,也可以重新赋值, 
int* array_at(Array *a, int index)
{  
    if (index >= a->size) {
        array_inflate(a, ((index / BLOCK_SIZE + 1) *BLOCK_SIZE ) - a->size);
    }
    return &(a->array[index]);
}
//对数组进行扩容
void array_inflate(Array *a, int more_size) {
    printf("扩容前的大小=%d
", a->size);
    int *p = (char*)malloc(sizeof(int)* (a->size + more_size));
    int i = 0;
    /*for (; i < a->size; i++) {
        p[i] = a->array[i];
    }*/
    memcpy(p,a->array);
    free(a->array);
    a->array = p;
    a->size += more_size;
    printf("扩容后的大小=%d
", a->size);
}




int main() 
{
    //可变数组的缺陷:拷贝数据的时间,内存受限的情况下,当size超过一半的内存大小时,无法继续申请内存
    //    如 内存 16k, 当前array大小 已经达到8k ,剩余8k内存,然而申请 8K + block_size 大小内存时,系统内存不够用
    Array a = array_create(1);
    printf("接受的a的地址==>%x
", &a);
    *array_at(&a,3) = 10;
    printf("%d
", *array_at(&a, 3));
    int number = 0;
    int cnt = 0;
    while (number != -1) {
        scanf("%d", &number);
        if (number != -1) {
            *(array_at(&a, cnt++)) = number;
        }
    }
    array_free(&a);
 


    return 0;
}
自定义容器实现

自定义链表简单实现

#include <stdio.h>
#include <stdlib.h>
#include "node.h"


//typedef struct _node {
//    int value;
//    struct _node *next;
//}Node;



typedef struct  _list{
    Node *head ;
    Node *tail;
}List;

void add(List *list, int number);
void list_print(List *list);
int list_remove(List *list, int number);
int list_clear(List *list);

int main()
{
/*
    int number;
    do {
        scanf("输入一个整数%d", &number);
        if (number != -1) {
            add(&list, number);
        }
    } while (number != -1);*/

    List list;
    list.head = NULL;
    int len = 8;
    int arr[] = { 1,2,3,4,5,6,7,8};
    int i;
    for ( i = 0; i < len; i++)
    {
        printf("第%d次
",i);
        add(&list, arr[i]);
    }
    list_print(&list);
    list_remove(&list, 1);


    List list1;
    list1.head = NULL;
    int res = list_remove(&list, 1);

    if (res > 0) {

        printf("删除成功
");
    }
    list_clear(&list);
    list_print(&list);

    printf("Hello World! linked-list
");
    return 0;

}

//清除所有的链表

int list_clear(List *list) {
    Node *p;
    Node *q;
    for (p = list->head; p; p = q) {
        q = p->next;
        free(p);
    }
    printf("clear ...list size==>%d
", sizeof(&list));
    //list->head = NULL;

}

//移除链表中某一个数据
int list_remove(List *list, int number) {
    //问题1.数据是否存在
    //问题2.边界处理?数据是在第一个
    Node* p;
    Node* pTemp;
    int res = -1;
    if (list->head) {
        for (pTemp = NULL, p = list->head; p; pTemp = p, p = p->next) {
            if (number == p->value) {
                if (pTemp) {
                    pTemp->next = p->next;
                }
                else {
                    list->head = p->next;
                }
                free(p);
                res = 1;
                break;
            }
        }
    }
    
    return res;

}


//输出链表中所有的数据
void list_print(List *list) {
    Node *p ;

    if (list->head) {
        printf("the list is null...
");
        return;
    }
    for (p = list->head; p; p = p->next) {
        printf("-%d", p->value);
    }
    printf("
");
}

//将一个数据添加到列表当中
void add(List* pList,int number) {
    Node *p = (Node*)malloc(sizeof(Node));
    p->value = number;
    p->next = NULL;
    Node* last = pList->head;
    if (last) {
        while (last->next)
        {
            last = last->next;
        }
        last->next = p;
    }
    else {
        pList->head = p;
    }
}
自定义链表
原文地址:https://www.cnblogs.com/shenwenbo/p/14972528.html