• 关于C语言的一些总结(菜鸟版本)


    typedef unsigned int  uint16;

    define  num 8

    数组int a[10]   typedef struct ab {uint16 a; uint16 b; uint16 c;}abb;   abb stu[10];    void fun() ;    其中数组的名字a 和stu   函数名fun代表首地址,

    但是,如果是单独的结构体,abb stu;  stu并不代表首地址,首地址要用到&符号

     

    a+3 代表第三元素的地址  a[3]代表第三个元素  同理   stu[1]不是代表地址,而是第二个结构体本身,可以这样复制stu[1].a=2;

    stu+1才代表第二个结构体的地址

    与&stu[1]是一个意思

     

    printf

    字符 对应数据类型 含义
    d / i int 接受整数值并将它表示为有符号的十进制整数,i是老式写法
    o unsigned int 无符号8进制整数
    u
    unsigned int 无符号10进制整数
    x / X
    unsigned int 无符号16进制整数,x对应的是abcdef,X对应的是ABCDEF
    f
    float或double 单精度浮点数双精度浮点数
    e / E
    double 科学计数法表示的数,此处"e"的大小写代表在输出时用的“e”的大小写
    g / G
    double 使用以上两种中最短的形式,大小写的使用同%e和%E
    c
    char 字符型。可以把输入的数字按照ASCII码相应转换为对应的字符
    s / S
    char * / wchar_t * 字符串。输出字符串中的字符直至字符串中的空字符(字符串以'‘结尾,这个''即空字符)
    p
    void * 以16进制形式输出指针
    n int * 到此字符之前为止,一共输出的字符个数,不输出文本
    %
    无输入 不进行转换,输出字符‘%’(百分号)本身
    注:%g、%G在小数点位数四位或指数大于等于精度时用%e、%E,否则用%f。

     

     

    int main(int argc, char ** argv)       int main(int argc,char * argv[])

     

    int a=10 b=20 c=30

    printf("%d%d%d",a+b+c,b=b*2,c=c*2) ;   结果 110  40  60  因为函数的参数默认是从右到左处理的。

     

     

    char *p  p是指针变量,其值是可以修改的,但是不能通过P修改指向的字符串

    char p【】   p是数组变量,其值不可以修改,但是可以修改p指向的字符串

     

     

    连接符 #define XXX(a,b)  a##b    //##  是连接符

    printf(“%d ”,XXX(fun,2)(100));

     

    等价于 fun2(100);

     

     

     

     

     

     

    地址空间:为了比较直观的知道地址空间的大小,可记以下规律。4K     --> 0x00001000,

                                                                                                64K   --> 0x00010000,

                                                                                                1M    --> 0x00100000, 

                                                                                                  16M --> 0x01000000, 

                                                                                                256M-->   0x10000000,           
    3个0 是4K                         4个0 是64K                      5个0 是1M                     6个0 是16M                 7个0 是256M

    为什么3个0表示的空间大小是4K小呢? 地址从0x00000000起始,到0x00001000其间则有16*16*16个地址,每一个地址表示1bit空间大小。 那其空间大小是:(16*16*16)/1024= 4 k

    每个地址,如0x10000000单个地址,它是16进制,所以每一个数值需要4个bit来表示(2的4次方=16), 所以其占用空间32bit。

    为什么bit成为了最小数据单元?(以下为个人的理解) 电子电路它只有0,1两种信号(再傻瓜式的说明就是只有通电或断电),所以我们定义了能标志0或1的单元为bit。然后我们开始采用顺序堆积很多这样单元,就能为我们记录很多标识(称作数据或信息)。
    但是是谁在控制这个16进制的地址呢,是CPU吗?或说是这么多16进制的数值(编号)它又是保存在那呢?每个bit空间,是不可能存放一个32位的16进制的,就算可以也没有意义。那CPU它又是根据什么来进行寻址呢?它是如何做到可以直接跳转读取到指定的地址?

    2.

    名称 标识符 大小 表示范围
    短整型 shortint 1字节 -128~127
    整型 integer 2字节 -32768~32767(-2^15~2^15-1)
    长整型 longint 4字节 (-2^31~2^31-1)
    64位长整形 int64 8字节 -2^63~2^63-1
    字节型 byte 1字节 0~255
    字型 word 2字节 0~65536
    双字型 dword 4字节
    四字型 qword 8字节 0~2^64-1
    允许的计算符是+(加) -(减) *(乘) div(整除) mod(求余)and (与)or (或)xor(异或)
     

    1.typdef void (*funcptr)(void);的解释说明( 函数指针)    原型初见于stm32的IAP bootloader编程“跳转地址函数”
    定义一个函数指针类型。
    比如你有三个函数:
    void hello(void) { printf("你好!"); }
    void bye(void) { printf("再见!"); }
    void ok(void) { printf("好的!"); }

    typdef void (*funcptr)(void);
    这样就构造了一个通用的函数
    你用的时候可以这样:
    void speak(int id)
    {
       funcptr words[3] = {&hello, &bye, &ok};
       funcptr fun = words[id];
       (*fun)();
    }

    这样的话,如果speak(0)就会显示“你好!”
    speak(1)就会显示“再见!”
    speak(2)就会显示“好的!”

    用于处理参数和返回值的形式都一样,但是功能不确定的一组函数,可以使用函数指针。
    比如算术运算符,加、减、乘、除,都可以用typedef int (*calc)(int,int)代表,等、

    2.(指针和形参传递)

    1.       零值比较

    一般意义上的零值有布尔型,整型,指针,浮点型。

    (1)             布尔型:C语言里面没有布尔类型,但是C99标准提供了一个库来表示,头文件为<stdbool.h>,其表示为bool mybool = true;注意都是小写,其实在C语言windows里面也定义了一个BOOL来区别于C++bool

    1)         #include <stdbool.h>

    2)          

    3)         int main(void)

    4)         {

    5)                  bool mybool = true;

    6)                  if(mybool)

    7)                            printf("mybool is true ");

    8)                  else

    9)                            printf("mybool is false ");

    10)          printf("c bool size is %d ", sizeof(mybool));

    11)               return 0;

    12)      }

    结果为:

    mybool is true

    c bool size is 4

     

    注意和C++的布尔型的区别,C语言里面的布尔型是用整数来代替的,零是假,任何非零的值为真,C++的布尔型是一个一个字节的变量。

    1)         //#include <stdbool.h>

    2)         #include <iostream>

    3)         using namespace std;

    4)         int main(void)

    5)         {

    6)         bool mybool = true;

    7)         if(mybool)

    8)         cout<<"mybool is true"<<endl;

    9)         else

    10)      cout<<"mybool is false"<<endl;

    11)      cout<<"c++ bool size is "<<sizeof(mybool)<<endl;

    12)      return 0;

    13)      }

    结果为:

    mybool is true

    c++ bool size is 1

    (2)             整型:同类bool型用法一样 int test = 0;

    if(test){

    }

    else{

    }

    (3)             指针:指针的零值为空指针NULL int *ptest = NULL;

    if(test == NULL){

    }

    else{

    }

    (4)             浮点型:浮点型的数据与零值比较不是直接测试与零是否相等,而是测试是否在0值左右的一个范围内。

    if(fabs(flag2) < 1e-5)

            printf("flag2 is 0 ");

        else

            printf("flsg2 is not 0 ");

    2.       函数形参传递

    1Strcpy函数的实现:

    char *mystrcpy(char *des, const char *sur)

    {

    char *p = des;

    assert((des !=NULL ) && (sur != NULL));

    while((*des++=*sur++) != '');

    return p;

    }

    2)示例1

    1)       void getmemory1(char *p)

    2)       {

    3)       p = (char *)malloc(100);

    4)       }

    5)       void test1(void)

    6)       {

    7)       char *str = NULL;

    8)       getmemory1(str);

    9)       strcpy(str, "hello world1 ");

    10)    printf(str);

    11)      }

    由于传入函数getmemory1的参数为指针,编译器为其准备一个副本_p传入,存在在系统栈里面,我们在getmemory1函数里面,为其动态分配空间存在于堆上,但是里面使用的是p的副本,分配空间的头指针指向的是_p,而不是p,所有该函数结束时p的值仍然没有改变,这里函数结束后不会把分配的空间释放掉,因为其分配的空间在堆上,如果程序员不释放的话其空间要在程序结束后由操作系统收回。测试函数使用未改变的的指针,其值为NULL,所有会出错。

    3)示例2

    1)       char* getmemory2(void)

    2)       {

    3)      char p[] = "hello world2 ";//在栈上

    4)       return p;

    5)       }

    6)       void test2(void)

    7)       {

    8)       char *str = NULL;

    9)       str = getmemory2();

    10)    printf(str);

    11)      }

    由于函数getmemory2在内部使用了char p[] = "hello world2 "; 所有我们这里说一下他和

    char  *p1 = "hello world2 ";的区别,首先char p[] = "hello world2 "都是存放在栈上的,函数执行完会自动释放,而char  *p1 = "hello world2 ";却不一样,char *p1存放在栈上这与前面一样,但是"hello world2 "却是存放在常量区的,程序结束后由系统释放 ,而且char p[]是一个数组名,为常量,而char  *p1不是,在getmemory2函数中,char p[] = "hello world2 "都是存放在栈上的,函数作用范围结束后会自动释放,所以,即使返回了p指针,我们打印出来的字符串也是乱码但是如果将函数内部char p[] = "hello world2 "改变为char  *p1 = "hello world2 ",则不会出错,程序代码如下:

    1)         char* getmemory2(void)

    2)         {

    3)         char *p1= "hello world2 ";

    4)         return p1;

    5)         }

    6)         void test2(void)

    7)         {

    8)         char *str = NULL;

    9)         str = getmemory2();

    10)      printf(str);

    11)      }

    从这里我们可以认为,char p[] = "hello world2 "是一个字符型数组,p为数组名不可以改变,而char  *p1 = "hello world2 "是指针指向的字符串常量,p1为可变指针,而字符串常量存在常量区。

    (4)外传:字符串常量,我们可以知道"hello world2 "是一个字符串常量,并将第一个值的位置给一个指针p1,我们来看一下下面的表达式:

    "hello world2 "+1

    其实我咋一看,感觉这表达式没什么意义,在看了C和指针才知道,其实这个也是很有意思的,

    "hello world2 "+1指向的是字符串常量的第二个字符,这样我们干脆就把它当成一个指针来看,这样下面的表达式也就有了意义

    *"hello world2 "

    这个表达式很明显的意思就是取字符串常量的第一个字符,依次我们可以进行的运算就可以知道如

    "hello world2 "[3]; //等效于*("hello world2 "+3)

    注意:由于字符串常量位于常量区,他的生命周期是恒定不变的,而且由于是常量,它不允许改变它的值,是只读的。

    5)示例3

    1)         void getmemory3(char **p, int num)

    2)         {

    3)         *p = (char *)malloc(num);

    4)         }

    5)         void test3(void)

    6)         {

    7)         char *str = NULL;

    8)         int num = 100;

    9)         getmemory3(&str,num);

    10)      printf(str);

    11)      }

    这次这个示例可能有点难懂了,传入函数getmemory3可以说是指针的指针,假设这里编译器为其准备的副本为__p,那么*__p即是指向char类型的指针,那么我们可以像平常那样对其动态分配空间,你可能会有疑问,为什么这里可以为他动态分配呢,虽然编译值指定__p = p;

    但是他们指向的地址都是同一个,*__p =  *p,分配空间后的头指针付给*__P 相当于赋给了*p,但是最好不要用这个方法分配空间。

    注意:释放分配的空间后将指针设置为NULL,避免形成野指针。

    6)示例4

    1)         char* getmemory3(void)

    2)         {

    3)         char *p = (char *)malloc(100);

    4)         printf("len is %d ",strlen(mystrcpy(p, "hello mywold3")));

    5)         return p;

    6)         }

     

    7)         void test3(void)

    8)         {

    9)        char *str = NULL;

    10)      str = getmemory3();

    11)      printf(str);

    12)      }

    getmemory3函数里面,char *p = (char *)malloc(100);分配空间,虽然指针p存在于系统栈在函数结束后将消亡,但是分配的空间存在于堆不会,返回分配的首指针,使该动态分配的区域有指针指向,置于可用状态。

    3.       指针

    我们这里直接通过下面一段代码来讲解:

    char ch[7]="13579";

        char cr = 'm';

        char *cp = &cr;

        printf(" &cr is %0x ", &cr);//取cr变量的地址,也就是m存储的位置

        printf(" cp is %0x ", cp);/变量赋值的时候就是为m存储的位置

        printf(" &cp is %0x ", &cp);//取cp的地址

        printf(" *cp is %c ", *cp);//从存储m的位置,取出m

        cp = ch;

        printf(" *cp+1 is %c ", *cp+1);//从存储m的位置,取出m并将m的值加‘*’优先级高

        printf(" *(cp+1) is %c ", *(cp+1));//地址cp加单位字节,然后取出+1地址的内容

        printf(" cp is %0x ", cp)

        printf(" ++cp is %0x ", ++cp);//地址cp先加单位字节再使用

        printf(" cp is %0x ", cp);

        printf(" cp++ is %0x ", cp++);//地址cp先使用再加单位字节

        printf(" *cp is %c ", *cp);

        printf(" *++cp is %c ", *++cp);//*,++优先级相同,自右向左,先指针加1再取内容

        printf(" *cp is %c ", *cp);

        printf(" *cp++ is %c ", *cp++);//*,++优先级相同,自右向左,先取内容再指针加1

    //其实这里挺奇怪的 两者优先级相同,且是从右向左,那就应该是先++,但是我们这里可以这//样认为两者操作符没有挨着,所有遵循从左到右,先取值,再指针+1

        printf(" *cp is %c ", *cp);

        printf(" ++*cp is %c ", ++*cp);// *,++优先级相同,自右向左,先取内容再内容加1

  • 相关阅读:
    vue 组件开发 props 验证
    vue中$emit与$on
    vue中的 ref 和 $refs
    Animate.css动画特效
    Css Tada动画效果(Css Tada Animation Effect)--- shake抖动效果
    给某个dom对象添加动画fadeIn、fadeInDown、flipInY、jackInTheBox
    uniapp导航栏自定义按钮及点击事件
    uniapp的微信小程序,获取授权,获取中文街道地理位置
    在mac上如何用safari调试ios手机的移动端页面
    条件编译
  • 原文地址:https://www.cnblogs.com/darren-715/p/3456951.html
Copyright © 2020-2023  润新知