黑马程序员-07.C复杂数据类型

 ------   Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

1.变量类型

根据变量的作用域,可以分为:

 1).局部变量:

 1> 定义:在函数(代码块)内部定义的变量(包括函数的形参)

 2> 作用域:从定义变量的那一行开始,一直到代码块结束

 3> 生命周期:从定义变量的那一行开始分配存储空间,代码块结束后,就会被回收

 4> 没有固定的初始值

 2).全局变量

 1> 定义:在函数外面定义的变量

 2> 作用域:从定义变量的那一行开始,一直到文件结尾(能被后面的所有函数共享)

 3> 生命周期:程序一启动就会分配存储空间,程序退出时才会被销毁

 4> 默认的初始值就是0

  变量类型的练习
// 全局变量:a、b、c
// 局部变量:v1、v2、e、f

#include 
      
      
       
       
// 变量a的初值是10
int a = 10;

// 变量b的初值是0
// 变量c的初值是20
int b , c = 20;

int sum(int v1, int v2)
{
    return v1 + v2;
}

void test()
{
    b++;
    
    int i = 0;
    i++;
    
    printf("b=%d, i=%d\n", b, i);
}

int main()
{
    test();
    test();
    test();
    
    int e = 10;
    
    {
        {
            int f = 30;
        }
    }
    
    return 0;

      
      



2.结构体

1>定义结构体变量
 struct Person
    { // 里面的3个变量,可以称为是结构体的成员或者属性
        int age; // 年龄
        double height; // 身高
        char *name; // 姓名
    };

2>根据结构体变量,定义结构体变量
  struct Person p = {20, 1.55, "jack"};
    p.age = 30;
    p.name = "rose";
    
    printf("age=%d, name=%s, height=%f\n", p.age, p.name, p.height);
    
    /* 错误写法
    struct Person p2;
    p2 = {30, 1.67, "jake"};
    */
    
    struct Person p2 = {.height = 1.78, .name="jim", .age=30};
    //p2.age = 25;
3>结构体的内存分析

1)补齐算法(对齐算法)结构体所占用的存储空间 必须是 最大成员字节数的倍数

2)定义结构体类型(并不会分配存储空间)
3)定义结构体变量(真正分配存储空间)
4>定义结构体变量的3种方式

1> 先定义类型,再定义变量(分开定义)

 struct Student

 {

    int age;

 };

 struct Student stu;

 

 2> 定义类型的同时定义变量

 struct Student

 {

    int age;

 } stu;

 struct Student stu2;

 

 3> 定义类型的同时定义变量(省略了类型名称)

 struct

 {

    int age;

 } stu;


5>结构体类型的作用域

 1> 定义在函数外面:全局有效(从定义类型的那行开始,一直到文件结尾)

 2> 定义在函数(代码块)内部:局部有效(从定义类型的那行开始,一直到代码块结束)

6>结构体类型不能重复定义

7>结构体数组

1)定义

  struct RankRecord
    {
        int no; // 序号  4
        int score; // 积分 4
        char *name; // 名称 8
    };
2)初始化

 
struct RankRecord r1 = {1, "jack", 5000};
struct RankRecord r2 = {2, "jim", 500};
struct RankRecord r3 = {3, "jake",300};
------------------------------------------
 struct RankRecord records[3] =
    {
        {1, "jack", 5000},
        
        {2, "jim", 500},
        
        {3, "jake",300}
    };
    
    records[0].no = 4;
    // 错误写法
    //records[0] = {4, "rose", 9000};
    
    for (int i = 0; i<3; i++)
    {
        printf("%d\t%s\t%d\n", records[i].no, records[i].name, records[i].score);
    }
8>指向结构体的指针

#include 
       
       
        
        

/*
 1.指向结构体的指针的定义
 struct Student *p;
 
 2.利用指针访问结构体的成员
 1> (*p).成员名称
 2> p->成员名称
 
 */

int main()
{
    struct Student
    {
        int no;
        int age;
    };
    // 结构体变量
    struct Student stu = {1, 20};
    
    // 指针变量p将来指向struct Student类型的数据
    struct Student *p;
    
    // 指针变量p指向了stu变量
    p = &stu;
    
    p->age = 30;
    
    // 第一种方式
    printf("age=%d, no=%d\n", stu.age, stu.no);
    
    // 第二种方式
    printf("age=%d, no=%d\n", (*p).age, (*p).no);
    
    // 第三种方式
    printf("age=%d, no=%d\n", p->age, p->no);
    
    
    
    
    return 0;
}

       
       
9>结构体和函数

如果结构体作为函数参数,只是将实参结构体所有成员的值对应地赋值给了形参结构体的所有成员

修改函数内部结构体的成员不会影响外面的实参结构体


10>结构体和数组的区别

 数组:只能由多个相同类型的数据构成

 结构体:可以由多个不同类型的数据构成

3.枚举

1)定义枚举类型和变量
    enum Season
    {
        spring = 1,
        summer,
        autumn,
        winter
    };
    
    ---------------------------------------
    enum Season s = 100000;
    
    
    printf("%d\n", s);
    


4.宏定义

预处理命令

1).所有的预处理指令都是以#开头

2).预处理指令分3种

 1> 文件包含

 2> 条件编译

 3> 宏定义

预处理指令在代码翻译成0和1之前执行

预处理的位置是随便写的

预处理指令的作用域:从编写指令的那一行开始,一直到文件结尾,可以用#undef取消宏定义的作用

宏名一般用大写或者以k开头,变量名一般用小写

注意:

1)#undef COUNT

从这行开始,COUNT这个宏就失效

2)带参数的宏定义效率比函数高

5.条件编译

1)只要写了#if,在最后面必须加上#endif
2)定义的格式
#ifndef A
//#ifdef A
//#if !defined(A)
    printf("哈哈\n");
#endif

-----------------------------------
#if (A == 10)
    printf("a是10\n");
#elif (A == 5)
    printf("a是5\n");
#else
    printf("a其他值\n");
#endif

6.include

 1.<>表示系统自带的文件,""表示自定义的文件

 2.不允许循环包含,比如a.h包含b.h,b.h又包含a.h

7.typedef

1)作用:给已经存在的类型起一个新的名称

 

2)使用场合:

 1> 基本数据类型

 2> 指针

 3> 结构体

 4> 枚举

 5> 指向函数的指针

3)typedef 使用注意点 

#define String2 char *

s3才是char *指针,s4只是char

 String2 s3, s4;

typedefchar * String;

s1、s2是char *指针

String s1, s2;



8.static和extern对函数的作用

外部函数:定义的函数能被本文件和其他文件访问

 1> 默认情况下所有函数都是外部函数

 2> 不允许有同名的外部函数

 

 内部函数:定义的函数只能被本文件访问,其他文件不能访问

 1> 允许不同文件中有同名的内部函数

 

 static对函数的作用:

 1> 定义一个内部函数

 2> 声明一个内部函数

 

 extern对函数的作用:

 1> 完整地定义一个外部函数

 2> 完整地声明一个外部函数

 (extern可以省略,默认情况下声明和定义的函数都是外部函数)

static修饰局部变量的使用场合:

 1>.如果某个函数的调用频率特别高

 2>.这个函数内部的某个变量值是固定不变的

static修饰局部变量:

     1> 延长局部变量的生命周期:程序结束的时候,局部变量才会被销毁

     2> 并没有改变局部变量的作用域

     3> 所有的test函数都共享着一个变量b


9.递归

1)递归的二个条件:

1>函数自己调自己

2>必须有明确的返回值


2)用递归设计一个函数,用力计算b的n次方

include 
    
    
     
     
int pow2(int b, int n);

int main()
{
    int c = pow2(3, 2);
    
    printf("%d\n", c);
    return 0;
}

/*
 pow2(b, 0) == 1
 pow2(b, 1) == b == pow2(b, 0) * b
 pow2(b, 2) == b*b == pow2(b, 1) * b
 pow2(b, 3) == b*b*b == pow2(b, 2) * b
 
 1> n为0,结果肯定是1
 2> n>0,pow2(b, n) == pow2(b, n-1) * b
 */

int pow2(int b, int n)
{
    if (n <= 0) return 1;
    return pow2(b, n-1) * b;
}


    
    



           ------   Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值