翁愷C語言基礎學習——位運算概念,自定義容器
阿新 • • 發佈:2021-07-06
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\n", 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("\n"); } /* 位段, 常用於微控制器特殊暫存器結構,編譯器會安排其中位的排列,不可移植性 當所需要的位超過一個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\n", 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\n", 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\n", a->size); } int main() { //可變陣列的缺陷:拷貝資料的時間,記憶體受限的情況下,當size超過一半的記憶體大小時,無法繼續申請記憶體 // 如 記憶體 16k, 當前array大小 已經達到8k ,剩餘8k記憶體,然而申請 8K + block_size 大小記憶體時,系統記憶體不夠用 Array a = array_create(1); printf("接受的a的地址==>%x\n", &a); *array_at(&a,3) = 10; printf("%d\n", *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次\n",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("刪除成功\n"); } list_clear(&list); list_print(&list); printf("Hello World! linked-list\n"); 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\n", 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...\n"); return; } for (p = list->head; p; p = p->next) { printf("-%d", p->value); } printf("\n"); } //將一個數據新增到列表當中 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; } }自定義連結串列