总结一下C语言采坑之路
string.c
#include <stdio.h>#include <stdlib.h>/* 将字符串src_拼接到dst_后,将回拼接的串地址 */char *strcat(char *dst_, const char *src_){    char *str = dst_;    while (*str++);    --str; // 别看错了,--str是独立的一句,并不是while的循环体    while (*src_)    {        // 内联汇编和下面C语言代码等价        asm volatile("movl %0,%%ebx;/* 将src_的内存地址传送到基址寄存器ebx */ \                      movb (%%ebx),%%al;/* 从基址寄存器ebx为基址寻址,得到src_内存地址处的值,传送到8位通用寄存器al */ \                      movl %1,%%ebx;/* 将str的内存地址传送到基址寄存器ebx */ \                      movb %%al,(%%ebx); /* 将8位通用寄存器al存储的值,传送到以基址寄存器ebx为基址寻址,得到str的内存地址处 */"                     :                     : "m"(src_), "m"(str)                     : "memory", "al", "ebx");        // 与下面代码等价        // char temp= *src_;        // *str = temp; // 汇编寻址(*str)传送        str++;        src_++;    }    return dst_;}int main(int argc, char const *argv[]){    /* code */    // 正确用法    char a[] = "123";    char b[] = "456";    char *c[] = {b}; // 指针数组    printf("c:%s\n", *c);    // 错误用法    // char *a = "123";    // char *b = "456";    printf("a:%p\n", a); // 字符串与数组本身就是指针(头指针)    printf("b:%p\n", b);    strcat(a, b);    printf("%s\n", a);    system("pause");    return 0;}
bitmap_1.c
#include <stdio.h>#include <stdlib.h>#include <stdbool.h>#include <string.h>//定义每个Byte中有8个Bit位#include <memory.h>#define BYTESIZE 8void SetBit(char *p, int posi){    p = p + (posi / BYTESIZE);    *p = *p | (0x01 << (posi % BYTESIZE)); //将该Bit位赋值1,或操作会保留,位为1的二进制位    return;}void BitMapSortDemo(){    //为了简单起见,我们不考虑负数    int num[] = {3, 5, 2, 10, 6, 12, 8, 14, 9};    //BufferLen这个值是根据待排序的数据中最大值确定的    //待排序中的最大值是14,因此只需要2个Bytes(16个Bit)    //就可以了。    const int BufferLen = 2;    char p[BufferLen];    char *pBuffer = p;    //要将所有的Bit位置为0,否则结果不可预知。    memset(pBuffer, 0, BufferLen);    for (int i = 0; i < 9; i++)    {        //首先将相应Bit位上置为1        SetBit(pBuffer, num[i]);    }    //输出排序结果    for (int i = 0; i < BufferLen; i++) //每次处理一个字节(Byte)    {        for (int j = 0; j < BYTESIZE; j++) //处理该字节中的每个Bit位        {            //判断该位上是否是1,进行输出,这里的判断比较笨。            //首先得到该第j位的掩码(0x01<<j),将内存区中的            //位和此掩码作与操作。最后判断掩码是否和处理后的            //结果相同            printf("%c\n", *pBuffer);            printf("%d\n", (*pBuffer & (0x01 << j)));            // printf("\n");            printf("%d\n", (0x01 << j));            printf("\n");            if ((*pBuffer & (0x01 << j)) == (0x01 << j))            {                printf("%d ", i * BYTESIZE + j);            }        }        pBuffer++;    }}int main(int argc, char const *argv[]){    BitMapSortDemo();    system("pause");    return 0;}
bitmap_2.c
#include <stdio.h>#include <stdlib.h>#include <stdbool.h>#include <string.h>//定义每个Byte中有8个Bit位#include <memory.h>#define BYTESIZE 8#ifndef _LIB_STDINT_H#define _LIB_STDINT_Htypedef signed char int8_t;typedef signed short int int16_t;typedef signed int int32_t;typedef signed long long int int64_t;typedef unsigned char uint8_t;typedef unsigned short int uint16_t;typedef unsigned int uint32_t;typedef unsigned long long int uint64_t;#endif/*https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/06.07.md*/#define BITMAP_MASK 1 // 宏BITMAP_MASK其值为1,用来在位图中逐位判断,主要就是通过按位与‘&’来判断相应位是否为1。// struct bitmap中只定义了两个成员:位图的指针bits和位图的字节长度btmp_bytes_len。struct bitmap{    uint32_t btmp_bytes_len;    /* 在遍历位图时,整体上以字节为单位,细节上是以位为单位,所以此处位图的指针必须是单字节 */    uint8_t *bits; // *指针就是内存地址,这里声明的意思是指针的类型是uint8_t,仍然是内存地址。不同指针类型,在地址处取值时(*指针)的方法和长度不同而已};void SetBit(char *p, int posi);bool bitmap_scan_test(struct bitmap *btmp, uint32_t bit_idx);void printbit(char *pBuffer);void BitMapSortDemo(void);void BitMapSortDemo1(void);/* 判断bit_idx位是否为1,若为1则返回true,否则返回false */// bitmap_scan_test函数接受两个参数,分别是位图指针btmp和位索引bit_idx。其功能是判断位图btmp中的第bit_idx位是否为1,若为1,则返回true,否则返回false。// 如果bit_idx为10的话,byte_idx为1,bit_odd为2,字节索引1中的位1bool bitmap_scan_test(struct bitmap *btmp, uint32_t bit_idx){    uint32_t byte_idx = bit_idx / 8; // 向下取整用于索引数组下标    uint32_t bit_odd = bit_idx % 8;  // 取余用于索引数组内的位    uint8_t *bb = btmp->bits;    printf("%c\n", *bb);    uint8_t cc = btmp->bits[byte_idx];    printf("%c\n", cc);    int adds = btmp->bits[byte_idx];    char *dds = (char *)&adds; // 先转成int*,然后转换为char* 指针也有类型,主要是为了从内存中取值用做依据    printbit(dds);    uint32_t left = btmp->bits[byte_idx];    uint32_t right = (BITMAP_MASK << (8 - bit_odd - 1));    printbit((char *)&left);    printbit((char *)&right);    printf("left: %d,right: %d\n", left, right);    return (left & right);}// 打印一字节二进制void printbit(char *pBuffer){    int res = *pBuffer;    int count = 7;    printf("byte:");    for (int i = 0; i < 8; i++)    {        printf("%d", (res & (0x01 << count)) == 0 ? 0 : 1);        count--;    }    printf("\n");}void SetBit(char *p, int posi){    p = p + (posi / BYTESIZE);    *p = *p | (0x01 << (posi % BYTESIZE)); //将该Bit位赋值1,或操作会保留,位为1的二进制位    return;}void BitMapSortDemo(void){    //为了简单起见,我们不考虑负数    int num[] = {4, 7, 2, 5, 3};    //BufferLen这个值是根据待排序的数据中最大值确定的    //待排序中的最大值是14,因此只需要2个Bytes(16个Bit)    //就可以了。    const int BufferLen = 1;    char p[BufferLen];    char *pBuffer = p;    //要将所有的Bit位置为0,否则结果不可预知。    memset(pBuffer, 0, BufferLen);    for (int i = 0; i < 5; i++)    {        //首先将相应Bit位上置为1        SetBit(pBuffer, num[i]);    }    uint8_t *u = (uint8_t *)pBuffer;    struct bitmap map = {        1,        u};    bool r = bitmap_scan_test(&map, 6);    printf("%d\n", r);    // 0b10111100    // 0b00000001    //输出排序结果    for (int i = 0; i < BufferLen; i++) //每次处理一个字节(Byte)    {        printbit(pBuffer);        for (int j = 0; j < BYTESIZE; j++) //处理该字节中的每个Bit位        {            //判断该位上是否是1,进行输出,这里的判断比较笨。            //首先得到该第j位的掩码(0x01<<j),将内存区中的            //位和此掩码作与操作。最后判断掩码是否和处理后的            //结果相同            printf("*pBuffer:%c\n", *pBuffer);            printf("*pBuffer & (0x01 << j):%d\n", (*pBuffer & (0x01 << j)));            // printf("\n");            printf("(0x01 << j):%d\n", (0x01 << j));            printf("\n");            // 0b00000001 & 0b00000001 == 0b00000001            //  *pBuffer    0x01 << j     0x01 << j  j            // 0b10111100 & 0b00000001 == 0b00000001 0            // 0b10111100 & 0b00000010 == 0b00000010 1            // 0b10111100 & 0b00000100 == 0b00000100 2            // 0b10111100 & 0b00001000 == 0b00001000 3            if ((*pBuffer & (0x01 << j)) == (0x01 << j))            {                printf("%d ", i * BYTESIZE + j);            }        }        pBuffer++;    }}void BitMapSortDemo1(void){    //为了简单起见,我们不考虑负数    int num[] = {3, 5, 2, 10, 6, 12, 8, 14, 9};    int len = sizeof(num) / sizeof(num[0]);    printf("%d", len);    //BufferLen这个值是根据待排序的数据中最大值确定的    //待排序中的最大值是14,因此只需要2个Bytes(16个Bit)    //就可以了。    const int BufferLen = 2;    char p[BufferLen];    char *pBuffer = p;    //要将所有的Bit位置为0,否则结果不可预知。    memset(pBuffer, 0, BufferLen);    for (int i = 0; i < len; i++)    {        //首先将相应Bit位上置为1        SetBit(pBuffer, num[i]);    }    // uint8_t *u = (uint8_t *)pBuffer; // 指针也有类型,主要是为了从内存中取值用做依据    uint8_t *u = (uint8_t *)pBuffer;    printf("%p\n", u);    printf("%c\n", *u);    struct bitmap map = {        2,        u};    bool r = bitmap_scan_test(&map, 11);    printf("%d\n", r);    // 0b10111100    // 0b00000001    //输出排序结果    for (int i = 0; i < BufferLen; i++) //每次处理一个字节(Byte)    {        printbit(pBuffer);        for (int j = 0; j < BYTESIZE; j++) //处理该字节中的每个Bit位        {            //判断该位上是否是1,进行输出,这里的判断比较笨。            //首先得到该第j位的掩码(0x01<<j),将内存区中的            //位和此掩码作与操作。最后判断掩码是否和处理后的            //结果相同            printf("*pBuffer:%c\n", *pBuffer);            printf("*pBuffer & (0x01 << j):%d\n", (*pBuffer & (0x01 << j)));            // printf("\n");            printf("(0x01 << j):%d\n", (0x01 << j));            printf("\n");            // 0b00000001 & 0b00000001 == 0b00000001            //  *pBuffer    0x01 << j     0x01 << j  j            // 0b10111100 & 0b00000001 == 0b00000001 0            // 0b10111100 & 0b00000010 == 0b00000010 1            // 0b10111100 & 0b00000100 == 0b00000100 2            // 0b10111100 & 0b00001000 == 0b00001000 3            if ((*pBuffer & (0x01 << j)) == (0x01 << j))            {                printf("---%d---\n", i * BYTESIZE + j);            }        }        pBuffer++;    }}int main(int argc, char const *argv[]){    (void) argc;    (void) argv;    // BitMapSortDemo1();    BitMapSortDemo();    system("pause");    return 0;}
struct.c
#include <stdio.h>#include <stdlib.h>#include <memory.h>struct student generate(char name[], int age, int gender);void foo(void);struct student{    // 我指定的是32位,而非64位    char *name;          // name (指针4字节) 存储的是字符串指针也就是字符串的内存地址    unsigned int age;    // age (unsigned int 4字节)    unsigned int gender; // gender (unsigned int 4字节)};                       /*无论如何赋值结构体sizeof都是12字节*/struct student generate(char name[], int age, int gender){    char *ming = name;    struct student xiaoming = {        ming,        age,        gender};    printf("%s %d\n", name, sizeof(xiaoming));    printf("%d\n", *(unsigned int *)((unsigned int)&xiaoming + 4)); // 骚操作,拆解    // 目的是取结构体的第二个结构变量    // 1. &xiaoming 取结构体的指针即内存地址,起始内存地址    // 2. (unsigned int)&xiaoming 类型转换,方便加步长来寻址,如同汇编    // 3. (unsigned int)&xiaoming + 4 加上步长来寻址,步长位字节。这里是加上4字节,因为第一个结构体变量长度就是4字节,加上这个长度步长,跳过第一个结构体变量。    // 4. (unsigned int *)((unsigned int)&xiaoming + 4)) 得到第二个结构体变量内存地址后,类型转换为(unsigned int *)的指针    // 5. *(unsigned int *)((unsigned int)&xiaoming + 4)) 最后取指针地址,得到第二个结构体变量    return xiaoming;}void foo(void){    // char n[] = "哈哈";    generate("xiaoming", 16, 1);    generate("xiaoli", 18, 1);    generate("hahahahahahhahahahahahahahahahahahahahahhahaha", 20, 1);    generate("hello my name is xiaoliu", 120, 1);}int main(int argc, char const *argv[]){    (void)argc;    (void)argv;    printf("struct\n");    foo();    system("pause");    return 0;}
memory.c
#include <stdio.h>#include <stdlib.h>#include <memory.h>#define PSGE_SIZE 4096struct student{    char *name;          // name    unsigned int age;    // age    unsigned int gender; // gender};void foo(void);void foo(void){    void *p = malloc(PSGE_SIZE);    printf("0x%x\n", PSGE_SIZE);    memset(p, 0, PSGE_SIZE);    for (int i = 0; i < 13; i++)    {        printf("0x%x\n", *(int *)((unsigned int)p + i));    }    struct student *s = (struct student *)p;    printf("%x\n", sizeof(*s));}int main(int argc, char const *argv[]){    (void)argc;    (void)argv;    printf("struct\n");    foo();    system("pause");    return 0;}