zoukankan      html  css  js  c++  java
  • 关于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

  • 相关阅读:
    hdu 5387 Clock (模拟)
    CodeForces 300B Coach (并查集)
    hdu 3342 Legal or Not(拓扑排序)
    hdu 3853 LOOPS(概率DP)
    hdu 3076 ssworld VS DDD(概率dp)
    csu 1120 病毒(LICS 最长公共上升子序列)
    csu 1110 RMQ with Shifts (线段树单点更新)
    poj 1458 Common Subsequence(最大公共子序列)
    poj 2456 Aggressive cows (二分)
    HDU 1869 六度分离(floyd)
  • 原文地址:https://www.cnblogs.com/darren-715/p/3456951.html
Copyright © 2011-2022 走看看