C语言学习笔记(三)

Posted by alonealice on 2017-03-06

结构体和共同体

  1. 结构体,有点像java的类:struct 结构体名{成员列表}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct Man{
    int age;
    int sex;
    };
    或者:
    struct Man{
    int age;
    int sex;
    }man;
  2. 使用结构体的成员变量时使用结构体名.成员名

  3. 初始化结构体时可以直接加括号;也可以直接定义结构体数组初始化结构体数组:;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    man[]={{…},{…}}
    struct Man{
    int age;
    int sex;
    }man={2,4};

    或者是:
    struct Man{
    int age;
    int sex;
    }
    函数中:
    struct Man man={2,4};

    或者是:
    structMan{
    int age;
    int sex;
    }man[3];
    struct Man man[3];
    man={{},{},{}};
  4. 结构体指针:结构体类型 *指针名,使用其成员时:(*pMan).age(一定要括起来),还有一种方法是pMan->成员名,同时结构体指针不能直接初始化

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    struct Man{
    int age;
    int name;
    }m={10,89};


    struct Man *man;
    man=&m;
    printf("%d\n",(*man).age
    //或者是
    printf("%d",man->age);

    结果是:
    10
    10
  5. 结构体作为函数参数时,要使用关键字struct:void a(struct Man man)。传递结构体时需要传递的数据较大,所以可以传递结构体的指针代替void a(struct Man *man)

    1
    2
    3
    4
    5
    6
    7
    8
    int printMan(struct Man *m){
    printf("%d",m->name);
    return 0;
    }

    调用:
    printMan(&m);
    结果:89
  6. *malloc(unsigned int size),在内存中动态分配一块size大小的内存空间,会返回一个指针,错误时返回NULL;*calloc(unsigned n,unsigned size),该函数是在内存中动态分配n个长度为size的连续内存数组;free(void*ptr)该函数由指针指向内存去,使部分内存区能被其他变量使用

    1
    2
    3
    4
    struct Man* man;
    man=(struct Man*)malloc(sizeof(struct Man)); //申请Man大小的空间,再将该空间的指针强行转为 //struct Man*指针

    free(man); //将man内存空间回收掉
  7. 共同体和结构体很像:union 共同体名{成员变量列表}变量列表;区别是结构体定义了多个数据组成的特殊类型,共同体是所有数据成员的共享的内存,所有共同体在同一时刻只能有一个值,属于某一个数据成员。所以共同体的内存大小为其成员中最大的内存大小

    1
    2
    3
    4
    5
    6
    7
    8
    union Page{
    int p;
    char *t[1];
    };

    printf("%d", sizeof(union Page));

    结果:8
  8. union Man{int age;char name};union Man man;man.age=12;那么man.name也是12(12的ascii码)(测试多种情况,如字符串);其初始化为:man={12};

    1
    2
    3
    4
    5
    6
    7
    8
    9
    union Page{
    int p;
    char t[10];
    char* m[10];
    };

    union Page page={13,19};
    printf("%d,%d",*page.m,*page.t);
    结果:13,13
  9. 枚举enum 例子如下:如果Red为1,Green就自动会加1。使用枚举直接使用Red

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    enum Color(
    Rad,
    Green
    );
    enum Color(
    Rad=1,
    Green
    )
    printf("%d,%d",Rad,Green);
    结果:1,2

位运算和宏定义

  1. 位运算:&与,|或,~取反,^按位异或(两个位相同为0,不同为1),<<左移,>>右移

  2. 循环位移,将数据左移,左边移除部分重新添加到右边(a>>(32-T))|(a<T)

  3. 位段是特殊的结构类型,其所有的成员的长度均已二进制位为单位定义的,结构中的成员称为位段:结构机构名{类型变量名:长度; 类型变量名2:长度;}。如下:位段必须是int、unsigned和signed中的一种

    1
    2
    3
    4
    struct status{
    unsigned sign:1;
    unsigned zero:2;
    }flags;
  4. 位段可以加入无名位段,使后面位段从后面空位置开始存储:unsigned :0;可以使用%d等输出位段

  5. 宏定义 #define 宏名数据(不需要分号);使用#undef TEST终止宏定义(测试终止后继续使用,停止后再次使用,编译会出问题,比如在另一个方法中停止,经过测试稍微复杂一点程序就不能直接识别可以运行);宏定义用于预处理,只做符号替换,不分配内存

    1
    2
    3
    4
    5
    6
    7
    8
    printf("%d",TAG);
    #undef TAG;
    printf("%d",TAG); //编译不通过

    printf("%d\n",TAG);
    undef();
    printf("%d",TAG);
    结果为1 1
  6. 带参数的宏定义:#define 名(参数表)字符串,使用时参数最好带括号,不然可能会错。如#define MIX(a,b)(a*b+b),使用时如果是MIX(1,2),则正确,如实MIX(1,1+2),则会这样算11+2+1+2,结果错误,所以最好是((a)(b)+(b)),同时调用时最好也加括号,如5MIX(1,2),会成为51*2+2,所以最好在最外面加括号

    1
    2
    3
    4
    5
    6
    #define MIX(a,b)(a*b+b)

    printf("%d,%d",MIX(2,3),MIX(2+1,3));

    结果为:
    8,9
  7. #include<>和#include””一样,引入的头文件一般是.h,一般会在该文件中放置宏定义、结构、联合、枚举、typedef声明、外部函数声明,全局变量声明

  8. #if命令,含义是如果#if后面的表达式为真,则编译#if和#endif之间的代码,否则不编译:#if 表达式语句段 #endif,这个与if很像,#elif效果和else if一样,#else和else一样,最后都要#endif结尾

  9. #ifdef,判断宏定义常量是否被定义,@ifdef 宏名语句段 #endif,其他用法与#if一样;#ifndef作用与#ifdef相反,用法一样

  10. 预宏定义名:__LINE__ 当前被编译的代码的行号;__FILE__当前源文件的名称;__DATA__当前源文件的创建日期; __TIME__ 当前源文件的创建时间;__STDC__判断当前编译器是否是标准C,若是1则是,否则不是

  11. #line:改变行号和文件名 #line行号/文件名,该文件中输出行号和文件名会改变;#pragma:指定编译器状态 @pragma 参数,有一下几个参数:message:在输出窗口中输出信息;code_seg:设置程序中函数代码存放的代码段;once:保证头文件被编译一次

1
#line 12 "main.c";  //代表该行下面那行行号是12