zoukankan      html  css  js  c++  java
  • C语言学习(12)

    宏定义

    1.  宏定义:  理解为字符的替换

      语法:  #define   PI   3.14   //定义了一个宏,名字叫做PI,代表3.14这个小数

     1 #include <stdio.h>
     2 
     3 //定义一个宏
     4 #define PI 3.14
     5 #define N  88
     6 #define PATH  "/mnt/hgfs/share"
     7 
     8 int main()
     9 {
    10     int r=5;
    11     printf("%f
    ",PI);
    12     printf("%d
    ",N);
    13     printf("%s
    ",PATH);
    14     printf("%f
    ",PI*r*r);
    15 }

    注意:宏定义的名字一般都写成大写

    优点: 宏定义的执行效率很高(宏定义在预处理的时候就已经被替换了,而变量等到程序运行的时候才会加载到内存种参与运算),宏定义不是变量

    宏定义总共两种表现形式:

      形式1:  普通的宏定义      #define   PI   3.14      不要理解为变量了

      形式2:  宏函数                #define   ADD(a,b)    (a)+(b) 

     1 #include <stdio.h>
     2 
     3 //定义一个宏函数
     4 #define ADD(a,b) a+b
     5 int myadd(int a,int b)
     6 {
     7     return a+b;
     8 }
     9 int main()
    10 {
    11     int m=12;
    12     int n=13;
    13     printf("m+n is:%d
    ",ADD(m,n)); //迷惑初学者,跟函数调用类似(错误理解,宏函数不是真正的函数)
    14     printf("m+n is:%d
    ",myadd(m,n)); 
    15 }

      注意:    宏函数不是真正意义上的函数

        宏函数一定加上圆括号(为了防止出现优先级的问题) 

        宏定义如果有多行(一行写不下),必须加上续行符

    多行必须添加续行符

     1 #include <stdio.h>
     2 
     3 #define CMP(a,b) if(a>b) printf("a>b
    ");
     4 else printf("a<=b
    ")
     5     
     6 int main()
     7 {
     8     int m=78;
     9     int n=76;
    10     CMP(m,n);
    11 }

    C语言中printf和scanf的工作原理

    1.  scanf工作原理

      返回值:表示输入的符合要求的数据个数

      scanf和printf在系统中有个IO缓冲区,键盘输入的内容先进入到缓冲区,然后scanf从缓冲区里面读取符合要求的数据

      int getchar(void)      一次从缓冲区中读取一个字符(并把字符从缓冲区里面剔除

     1 #include <stdio.h>
     2 
     3 int main()
     4 {
     5     int n1,n2;
     6     int ret;
     7     int ret1;
     8 label:
     9     printf("请输入1个整数!
    ");
    10     ret=scanf("%d",&n1);  //hello
    
    11     //判断返回值
    12     if(ret!=1)  //你输入的不是整数
    13     {
    14         //清除掉io缓冲区中错误的字符
    15         while(getchar()!='
    ');
    16         goto label;
    17     }
    18     else
    19         printf("n1 is:%d
    ",n1);
    20 }

    2. printf工作原理

      先将输出的内容存放到IO缓冲区里面,遇到 或者return  0 主函数退出会自动刷新缓冲区(把缓冲区里面的内容显示在液晶屏上面)

    1 #include <stdio.h>
    2 
    3 int main()
    4 {
    5     printf("hello world");  //液晶屏上没有输出
    6     //printf("hello world
    ");  //输出了
    7     
    8     while(1);  //不让程序退出
    9 }

    C语言中的结构体,共用体,枚举

    1.  结构体:

    定义:   struct   结构体的名字

         {

        结构体成员;

          };

    比如:  struct  student   //把不同类型的数据打包成一个整体,程序员自定义了一种新的数据类型

           {

        char name[10];

        int age; 

            };

     1 #include <stdio.h>
     2 #include <string.h>
     3 struct student
     4 {
     5     char name[10];
     6     int age;
     7 };
     8 int main()
     9 {
    10     //一个班级10个学生
    11     struct student array[10];
    12     strcpy(array[0].name,"张三");;
    13     array[0].age=18;
    14     
    15     strcpy(array[1].name,"李四");;
    16     array[1].age=18;
    17     
    18     struct student *p=array;  //&array[0]
    19     printf("p->name is:%s
    ",p->name);
    20     printf("p->age is:%d
    ",p->age);
    21     
    22     p++;  //跳到下一个结构体
    23     
    24     printf("p->name is:%s
    ",p->name);
    25     printf("p->age is:%d
    ",p->age);
    26     
    27     
    28 }

    简化书写   typedef  struct  student

                       {

                                 char name[10];

                                  int age; 

                         }stu,*pstu;   

    stu就是 struct  student 类型名      stu  stu1; //stu1是个普通结构体变量 

    pstu就是struct  student  *类型名  pstu  stu4;  //stu4是个结构体指针变量

    结构体的初始化和使用:

    struct  student  stu1={“张三”,18};

    struct  student  stu1;

    stu1.name="张三";

    stu1.age=18;

    struct  student  stu1={.name="张三";.age=18;}

    struct  student  *stu1;

    stu1->name="张三";

    stu1->age=18;

    struct  student  *stu1;

    (*stu1).name="张三";

    (*stu1).age=18; 

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <stdlib.h>
     4 //定义一个结构体
     5 struct student
     6 {
     7     char name[10];
     8     int age;  
     9 };
    10 
    11 int main()
    12 {
    13     //写法一:定义结构体变量并初始化
    14     struct student stu1={"张三",18};  //int a;
    15     //普通结构体采用小数点引用成员
    16     printf("学生姓名:%s
    ",stu1.name);
    17     printf("学生年龄: %d
    ",stu1.age);
    18     
    19     //写法二:定义结构体变量没有立马初始化,后面才赋值
    20     struct student stu2;
    21     //stu2.name="张三";  //数组赋值只能用strcpy()
    22     strcpy(stu2.name,"李四");
    23     stu2.age=18;
    24   
    25     //写法三:linux内核代码中很常见
    26     //优点:可以不按照结构体定义的顺序赋值
    27     struct student stu3={
    28          .age=19,
    29          .name="王五" //小数点一定要写上
    30     };
    31     
    32     
    33     //写法四:定义结构体指针
    34     struct student *stu4=malloc(sizeof(struct student)); //野指针  Segmentation fault (core dumped)
    35     strcpy(stu4->name,"赵六");
    36     stu4->age=18;
    37     printf("学生姓名:%s
    ",stu4->name); 
    38     printf("学生年龄: %d
    ",stu4->age);
    39     
    40     //写法五:定义结构体指针
    41     struct student *stu5=malloc(sizeof(struct student));
    42     strcpy((*stu5).name,"赵七");
    43     (*stu5).age=18;  
    44    
    45    free(stu4);
    46    free(stu5);
    47 }

    普通结构体变量使用小数点引用成员:struct  student stu1      stu1.age;

     结构体指针使用->引用成员:    struct  student  *p;     p->age;‘

    2. 结构体大小规则

    32位系统

    第一步:找到结构体成员中数据类型最大的成员

    第二步:如果数据类型最大成员>=4字节,那么整个结构体按照4字节对齐

                   如果数据类型最大成员<4字节,那么整个结构体按照最大数据成员的大小对齐

    第三步:如果char和short连续挨在一起,需要合并

    64位系统

    第一步:找到结构体成员中数据类型最大的成员

    第二步:如果数据类型最大成员>=8字节,那么整个结构体按照8字节对齐

                   如果数据类型最大成员<8字节,那么整个结构体按照最大数据成员的大小对齐

    第三步:如果char和short连续挨在一起,需要合并(小心这一步跟32位系统的区别)

    3. 联合体(共用体)

    定义:  union  联合体的名字   //跟结构体写法类似

              {

              };

      union  sex

           {

               char  a;

               char  b;

            };

    普通联合体变量:  union  sex   sex1;    sex1.a='M';

    联合体指针:         union  sex   *p=&sex1;      p->b='W';

    联合体数组:         union  sex   array[10];

    跟结构体的区别,特点:

      联合体中所有的成员变量占用同一块内存区域(成员变量是互斥)

      联合体大小由最大成员的大小决定,也要满足字节对齐

     1 #include <stdio.h>
     2 union yy  //1<8    1字节对齐
     3 {
     4     char a;  //1
     5     char b;  //1
     6 };
     7 
     8 union tt  
     9 {
    10     char a;  
    11     int b;  
    12 };
    13 
    14 union uu  //  16字节
    15 {
    16     char a[11];  //11
    17     double b;  //8
    18     int c;
    19 };
    20 
    21 int main()
    22 {
    23     //定义联合体变量
    24     union yy y1;
    25     y1.a='@';  //只给a赋值了,b没有赋值
    26     y1.b='#'; //由于a和b共用同一块内存,b覆盖掉前面a的值
    27     
    28     printf("sizeof yy is:%lu
    ",sizeof(union yy)); //1
    29     printf("sizeof tt is:%lu
    ",sizeof(union tt)); //4
    30     printf("sizeof uu is:%lu
    ",sizeof(union uu)); //16
    31     union tt t1;
    32     t1.b=567;
    33     //请问t1.a是多少????  %d打印
    34     printf("t1.a is:%c   ASCII is:%d
    ",t1.a,t1.a);
    35     printf("y1.a is:%c
    ",y1.a);
    36     printf("y1.a is:%p
    ",&(y1.a));
    37     printf("y1.b is:%c
    ",y1.b);
    38     printf("y1.b is:%p
    ",&(y1.b));
    39 }

    实际用途:

    用来表示互斥的概念--》用联合体

    union  sex 

     {

         char  man;   //   'M'  --》男     'W' --》女

         char  woman;

     }

    4. 枚举:

    定义:  enum   枚举的名字  {枚举数据}

    enum  day {mon,tues,wen};

    enum  color  {red, green  blue};

     1 #include <stdio.h>
     2 
     3 //enum day {mon,tues,wen};  //默认情况下三个枚举变量值:分别是 0  1  2
     4 
     5 //enum day {mon,tues=7,wen}; // 0  7  8
     6 enum color {red,green,blue,yellow,black};
     7    //0  1  2 3 4 5 6 一个星期的七天 可读性差
     8 enum day {mon,tues=7,wen,tir,fri=2,sat}; // 0 7 8 9 2 3
     9 
    10 struct car  //小汽车
    11 {
    12     char name[10]; //品牌
    13     enum color carcolor; //车的颜色
    14     float price;
    15 };
    16 int main()
    17 {
    18     //定义一台车
    19     struct car car1={"奔驰s600",black,2000000.0};
    20     
    21     printf("mon is:%d
    ",mon);
    22     printf("tues is:%d
    ",tues);
    23     printf("wen is:%d
    ",wen);
    24     printf("tir is:%d
    ",tir);
    25     printf("fri is:%d
    ",fri);
    26     printf("sat is:%d
    ",sat);
    27 }

    C语言中的头文件

    作用: 包含其它头文件

    结构体,联合体,枚举的定义

    全局变量,函数的声明

    内联函数定义

     宏定义

    头文件的标准写法:

    参考系统中标准头文件:  
    #ifndef   _XXXX_H     目的为了防止重复包含同一个头文件

    #define   _XXXX_H

    #endif

    头文件<>和“”区别:

    <>  --》多用于系统自带的头文件,编译器会自动去系统的环境变量中寻找这个头文件

    环境变量:系统的一个默认路径/usr/include

    “”   --》多用于自定义的头文件,编译器会自动从当前路径下寻找这个头文件,如果当前路径下面没有,就去环境变量中找

    C语言程序编译的四个过程

    hello.c源文件  --->hello 可执行程序  经历四个过程: 预处理--》编译--》汇编--》链接生成可执行程序

    C语言的条件编译(跟宏定义配合使用)

    1. 作用: 满足条件就会帮你编译代码,不满足,就不编译(代码写了跟没写一样,被注释掉了)

    2. 写法一:

      #if  宏定义  //判断宏定义的值是真还是假

        代码;

      #else

        代码;

      #endif

    变形形式:  #if    #elif    #else   #endif

    写法二:

      #ifdef  宏定义    //宏定义定义了就执行,不是判断真假

        代码;

      #else     //没有定义

        代码;

      #endif

    写法三:

      #ifndef  宏定义   //  宏定义没有定义就执行

        代码;

      #else   //定义了就执行

        代码;

      #endif

    注意:以上都是完整的标准写法,  #else可以写也可以不写的

    作业:

    1.   scanf("%d",&n);   //   34hhh   不正确的整数

    #include <stdio.h>
    
    int main()
    {
        int n;
        int ret;
    label:
        printf("请输入整数!
    ");
    
        ret=scanf("%d",&n); //34hhh
        if(ret!=1)
        {
            //清空缓冲区
            while(getchar()!='
    ');
            goto label;
        }
        else if(ret==1&&getchar()=='
    ')  //正确的整数   34
    
            printf("正确的整数:%d
    ",n);
        else if(ret==1&&getchar()!='
    ') //数字后面有字符  34yut
    
        {
            printf("你输入的数字后面还有字符!!!!
    ");
            //清空缓冲区
            while(getchar()!='
    ');
            goto label;
        }
    }
    View Code
  • 相关阅读:
    【第40套模拟题】【noip2011_mayan】解题报告【map】【数论】【dfs】
    【模拟题(63550802...)】解题报告【贪心】【拓扑排序】【找规律】【树相关】
    【模拟题(电子科大MaxKU)】解题报告【树形问题】【矩阵乘法】【快速幂】【数论】
    IMemoryBufferReference and IMemoryBufferByteAccess
    SoftwareBitmap and BitmapEncoder in Windows.Graphics.Imaging Namespace
    Windows UPnP APIs
    编译Android技术总结
    Windows函数转发器
    Two Ways in Delphi to Get IP Address on Android
    Delphi Call getifaddrs and freeifaddrs on Android
  • 原文地址:https://www.cnblogs.com/xiaojian98/p/12993016.html
Copyright © 2011-2022 走看看