C语言--变量类型


根据变量的作用域,可以分为:
1.局部变量:
1>在函数(代码块)内部定义的变量,包括函数的形参
2>作用域:从定义变量的那一行开始,一直到代码块结束
3>生命周期:从定义变量的那一行开始分配存储空间,代码块结束后,就会被回收。
4>没有固定的初始值。

2.全局变量:
1>定义:在函数外面定义的变量
2>作用域:从定义变量的那一行开始,一直到文件结尾(能被后面的所有函数共享)
3>生命周期:程序一启动就会分配存储空间,程序退出时才会被销毁。
4>默认的初始值就是0。
   
代码示例:
//全局变量:a,b,c
//局部变量:v1,v2,i
#include<stdio.h>
int a=10;
int b,c=20;
int sum(int v1,int v2)
{
     return v1+v2;
}
void test()
{
b++;     //全局变量
int i=0;    //局部变量,每次调用都为初值0
i++;
printf("b=%d,i=%d\n",b,i);
}
int main()
{
//调用3次
test();     //1,1
test();     //2,1
test();     //3,1
}



构造类型:
数组:只能由多个相同类型的数据构成
结构体:可以由多个不同类型的数据构成               
#include<stdio.h>
int main()
{
       //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={40,1.23,"fuck"};
*/

struct Person p2={.height=1.24,.name="tom",.age=30};

return 0;
}



内存分析
void test()
{
  //1.定义结构体类型(并不会分配存储空间)
    struct Date
    {
        int year;
        int month;
        int day;
    };
   
    // 2.定义结构体变量(真正分配存储空间)
    struct Date d1 = {2011, 4, 10};
   
    struct Date d2 = {2012, 8, 9};
   
   // 会将d1所有成员的值对应地赋值给d2的所有成员
    d2 = d1;     
    //只是修改d2对应的year的值,不会影响到d1
    d2.year = 2010;
}


补齐算法(对齐算法),其结构体占用空间为最大成员占用空间的倍数。
struct Student
{
     int age;     //4个字节
     char *name;     //8个字节
};
struct Student stu;
stu.age=20;
stu.name="jack";

stu占用16个字节

定义变量的多种方式:

定义变量的第1种方式:先定义类型,再定义变量(分开定义)
//1.类型
struct Student
{
     int age;
    
};
//2.变量
struct Student stu;

定义变量的第2种方式:定义类型的同时定义变量
这段代码做了两件事情
1.定义结构体类型
2.利用新定义好的类型来定义变量
struct Student
{
     int age;
     
}stu;

struct  Student stu2;



定义结构体变量的第3种方式:定义类型同时定义变量(省略了类型名称)
struct {
     int age;
}stu;
缺点:不能重用

结构体类型不能重复定义
     struct Student
     {
          int age;
     };
     
     struct Student
     {
          double height;
     };
     
     struct Student stu;

     错误写法:结构体类型重复定义
     struct Student
     {
          int age;
    
     } stu;
     
     struct Student
     {
          int age;
    
     } stu2;

结构体类型作用域,从定义类型的那一行开始,一直到代码块结束。
 1> 定义在函数外面:全局有效(从定义类型的那行开始,一直到文件结尾)
 2> 定义在函数(代码块)内部:局部有效(从定义类型的那行开始,一直到代码块结束)


结构体数组
struct RankRecord
    {
        int no; // 序号  4
        int score; // 积分 4
        char *name; // 名称 8
    };
每个结构体变量占用16个字节


struct RankRecord records[3] =
    {
        {1, "jack", 5000},
       
        {2, "jim", 500},
       
        {3, "jake",300}
    };
//相当于   int age[3] = {19,20,21}
     
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);
    }

结构体指针
1.指向结构体的指针的定义
struct Student *p;

2.利用指针访问结构体的成员
1> (*p).成员名称
2> p->成员名称


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);
   

结构体嵌套定义

 struct Date
    {
        int year;
        int month;
        int day;
    };
   
   
    // 类型
    struct Student
    {
        int no; // 学号
       
        struct Date birthday; // 生日
       
        struct Date ruxueDate; // 入学日期
       
        // 这种写法是错误的,不能在结构体内包含自己
        //struct Student stu;
    };
   
   
    struct Student stu = {1, {2000, 9, 10}, {2012, 9, 10}};
   
    printf("year=%d,month=%d,day=%d\n", stu.birthday.year, stu.birthday.month, stu.birthday.day);
    
 枚举
用于变量有固定几个取值时。
enum Sex { Man, Woman, Unkown};


// 1.定义枚举类型
enum Season
    {     //整型常量
        spring ,     
        summer,
        autumn,
        winter
    };
 // 2.定义枚举变量
    enum Season s =spring;

总结:
一、基本数据类型
1.int
1> long int、long:8个字节  %ld
2> short int、short:2个字节 %d %i
3> unsigned int、unsigned:4个字节 %zd
4> signed int、signed、int:一样,4个字节 %d %i

2.float\double  小数
1> float :4个字节 %f     小数位少
2> double:8个字节 %f     小数位多     %.2f保留两位小数

3.char
1> 1个字节 %c %d
2> char类型保存在内存中的是它的ASCII值
'A' --> 65

二、构造类型
1.数组
1> 只能由同一种类型的数据组成
2> 定义:数据类型 数组名[元素个数];
int age[3];

2.结构体
1> 可以由不同类型的数据组成
2> 先定义类型,再利用类型定义变量

三、指针类型
1.变量的定义
int *p;

2.间接操作变量的值
int a = 10;
p = &a;
*p = 20;

四、枚举类型
使用场合:当一个变量只允许有几个固定取值



宏定义

 1.所有的预处理指令都是以#开头
2.预处理指令分3种
1> 宏定义
2> 条件编译
3> 文件包含
3.预处理指令在代码翻译成0和1之前执行
4.预处理的位置是随便写的
5.预处理指令的作用域:从编写指令的那一行开始,一直到文件结尾,可以用#undef取消宏定义的作用
6.宏名一般用大写或者以k开头,变量名一般用小写,规范问题!

  #define COUNT 4

 char *name = "COUNT";
   
    printf("%s\n", name);
   
  
   
    int ages[COUNT] = {1, 2, 67, 89};
   
   
   
    for ( int i = 0; i<COUNT; i++) {
        printf("%d\n", ages[i]);
    }
   
    // 从这行开始,COUNT这个宏就失效
#undef COUNT
   
    int a = COUNT;



带参数的宏定义

带参数的宏定义效率比函数高,宏定义的本质是是 替换,并不会运算。

#define sum(v1, v2) ((v1)+(v2))

#define pingfang(a) ((a)*(a))

int c = pingfang(5+5)/pingfang(2);

int c = sum(2, 3) * sum(6, 4);



typedef  起别名

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

2.使用场合:

1> 基本数据类型
typedef int MyInt;
MyInt i = 10;

2> 指针
typedef char * String;
String name = "jack";

3> 结构体
struct Student
{
    int age;
};
typedef struct Student MyStu;

---------------------------------------------

typedef  struct Student
{
    int age;
} MyStu;

-----------------------------------------
typedef struct
{
    int age;
} MyStu;

-----------------------------------------

struct Person
{
    int age;
};

typedef struct Person * PersonPoint;

-----------------------------------------------

typedef struct Person
{
    int age;
} * PersonPoint;


 4> 枚举
enum Sex {Man, Woman};
typedef enum Sex MySex;

-----------------------------------------
typedef enum {
    Man,
    Woman
} MySex;

 5> 指向函数的指针

typedef int (*MyPoint)(int, int);

int minus(int a, int b)
{
    return a - b;
}

int sum(int a, int b)
{
    return a + b;
}

     MyPoint p = sum;
     MyPoint p2 = minus;
   等同于如下两句:
    //int (*p)(int, int) = sum;
    //int (*p2)(int, int) = minus;
    
 p(10, 11);


--------------------------------
#define与typedef区别
#define只是纯粹的文本替换,typedef起别名其本质还是类型。

#define String2 char *
typedef char * String;

 //s1、s2是char *指针
    String s1, s2;
    /*
     String s1;
     String s2;
     */
    s1 = "jack";
    s2 = "rose";

    // s3才是char *指针,s4只是char
    String2 s3, s4;
    /*
    char *s3, s4;
    char *s3;
    char s4;



条件编译          只要写了#if,在最后面必须加上#endif
#if (A == 10)
    printf("a是10\n");
#elif (A == 5)
    printf("a是5\n");
#else
    printf("a其他值\n");
#endif

--------------------------------
如果没有宏定义
//#define A 5
#ifndef A
//#ifdef A
//#if !defined(A)
    printf("哈哈\n");
#endif


递归

 递归的2个条件:
1.函数自己调用自己
2.必须有个明确的返回值

例子:设计一个函数,用来计算b的n次方

普通的for循环
    int pow2(int b, int n)
{
for (int i = 0; i<n; i++)
    {
        result *= b;
    }
}

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值