malloc()函数、结构体、共用体、枚举 2月1日学习笔记

一、malloc()函数

void* malloc(size_t size);

用于动态分配内存空间。

link = (int*)malloc(size(int)); //申请一段为int大小的内存空间。

int* p = (int*)malloc(sizeof(int)) 分配了一个 int 类型大小的内存空间,并将其起始地址赋给指针 p

malloc 分配的内存空间是在堆(heap)上。堆是程序运行时动态分配内存的一部分,与栈上的局部变量不同。堆上的内存需要手动管理,当不再需要时,应使用 free 函数释放已分配的内存空间,以避免内存泄漏。

malloc 返回的是 void 指针,这意味着它可以用来分配任何数据类型的内存空间。但是,分配的内存需要根据特定的数据类型进行强制类型转换以进行使用。例如,如果要分配一个整型数组的内存空间,可以使用 int* p = (int*)malloc(sizeof(int) * n),其中 n 是数组的大小。

#include 
#include 

int main() {
    int n;
    printf("请输入数组大小:");
    scanf("%d", &n);

    // 使用 malloc 在堆上分配整型数组的内存空间
    int* arr = (int*)malloc(sizeof(int) * n);
    if (arr == NULL) {
        printf("内存分配失败\n");
        return 1;
    }

    // 给数组赋值
    for (int i = 0; i < n; i++) {
        arr[i] = i + 1;
    }

    // 输出数组的元素
    printf("数组的元素为:");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    // 释放分配的内存空间
    free(arr);

    return 0;
}

 

二、结构体

语法:
struct 结构体类型名
{
   数据成员列表;
};
//定义了一个 "数据类型"  --- 用户自定义的数据类型 

//通常在函数外部声明结构类型,这样就可以被多个函数所使用了

结构体类型可以定义在函数内部,但这样结构体的作用域就只有这个函数内部了。

struct student
{
   //name 
   char name[20]; //成员变量  各个成员变量之间 用分号隔开
   //age
   unsigned char age;//0~255 -128~127
   //score
   float score;
   //...
}; //注意: 最后这个分号(;) 表示 --- 结构体类型定义完成 
struct student s; //s为 自己定义的这种结构体类型的一个变量 

访问结构体:
  . //结构体成员运算符 
  
 结构体变量名.成员变量名 

在使用变量名访问时  用 . 

在使用指针访问时 用  ->
结构体类型的变量.成员变量名 
结构体类型的指针->成员变量名

struct date{
        int month;
        int day;
        int year;
    };
    struct date today;
    //赋值方法一
    today.month=07;
    today.day=31;
    today.year=2014;
    //赋值方法二
    struct date today={07,31,2014};
    //赋值方法三
    struct date thismonth={.month=7,.year=2014};
    //赋值方法四
    today=(struct date){07,31,2014} 
    //结构体可以  这种赋值操作         thismonth=today,

结构体的定义的形式:
//形式1 先定义类型,后定义变量 
struct stu
{
...
};

struct stu s;


//形式2 定义类型的同时定义变量
struct stu
{
...
}s1,s2,*s3,s4[10];

struct stu s;
 
//形式3 省略了类型名 --如果只用一次,可以这样写

struct 
{
...
}s1,s2,*s3,s4[10];

 

#include 
#include 
struct student
{
	char name[20];
	int sno;
	float score;
};


void inputStuInfo(struct student *p,int len)
{
	int i = 0;
	for (i = 0; i < len;++i)
	{
		printf("name:");
		scanf("%s",(p+i)->name);
		printf("sno :");
		scanf("%d",&(p+i)->sno); //p[i].name
		printf("score:");
		scanf("%f",&(p+i)->score);
	}
}

void outputStuInfo(struct student *p,int len)
{
	
	int i = 0;
	printf("%10s|%10s|%10s\n","name","sno","score");
	for (i = 0; i < len;++i)
	{
		printf("%10s",p->name);
		printf("%10d",p->sno);
		printf("%10.2f\n",p->score);
		p++;
	}
}


void printMenu(void)
{
	printf("-----Welcome Use Student info System-----\n");
	printf("1 选择输入的学生人数\n");
	printf("2 输入信息\n");
	printf("3 查看学生信息\n");
	printf("0 退出 \n");
	printf(">");
}
int main(void)
{
	int n;
	int len = 0;
	struct student *s;

	while (1)
	{
		printMenu();
		scanf("%d",&n);
		switch(n)
		{
		case 0:
			  printf("exit----\n");
			  return 0;
		case 1:
			printf(">");
			scanf("%d",&len);
			s = malloc(len*sizeof(struct student));
			break;
		case 2:
			inputStuInfo(s,len);
			break;
		case 3:
			outputStuInfo(s,len);
			break;
		}
	}



	return 0;
}

结构体在内存中存储的对齐规则

1.在32位的平台上,默认都是按4字节对齐的。  64位的平台 默认是8字节
2.对于成员变量,
   各自在自己的自然边界上对齐。
//整个结构体的对齐 
3.如果 成员变量中有比4字节大。  
  此时 整个结构体按照4字节对齐。  //32位的平台
4.如果 成员变量中没有有比4字节大。
  此时 整个结构体按照最大的那个成员对齐。

自然边界对齐 
int -- 4字节 --- 能被4整除的地址编号上 
short -- 2字节 --- 能被2整除的地址编号上 
char -- 1字节 --- 能被1整除的地址编号上 

三、共用体union(联合体)

union 共用体名
{
  成员列表; //各个变量 
}; //表示定义一个共用体类型 

1.共用体 
  初始化 --- 只能给一个值,默认是给到第一个成员变量的

共同体中属性赋值会损坏其他属性的值。
2.共用体成员变量辅助 
  共用体用的数据最终存储的 --- 应该是最后一次给到的值。
  但是只能影响到 自己数据类型对应的空间中的数据


3.可以判断大小端 
4.实际用途 
  a.节省空间 
  b.进行数据转换 
  192.168.1.169 //ip本质是个 32位的数值 
  
5.共用体的大小  --是成员变量中最大的那个成员的大小

共用体大小计算,不一定就等于最大成员;

 6.共用体类型可以是函数参数,也可以是函数返回值类型 

union{
    char a[3];
    char b;
} A ;  // sizeof(A) = 3

union{
    char a[3];
    short b;
} B ;  // sizeof(B) = 4

union{
    char a[5];
    int  b;
} C ;  // sizeof(C) = 8

和结构体对齐规则一样。 

int isEndian(void)
{
    union demo
    {
        int a;
        char b;

    }d;
    d.a = 1;
    return d.b;
}

返回1 小端存储, 返回0 大端存储。 

四、枚举 enum

枚举:一枚一枚的列举

如果一个变量只有几种可能的值,则可以定义为枚举类型。
  所谓“枚举”是指将变量的值一一列举出来,
  变量的值只限于列举出来的值的范围内。

注意:
1.枚举  提高了代码可读性 
2.枚举 本质上是int类型 
  枚举 与 整型 类型兼容 
3.不足
  因为枚举类型 --- 本质上是个整型类型,
  所以枚举类型的变量的值,并不能真正限定在指定的哪些值范围中  
4.枚举类型 
  可以做函数 形参 和 返回值 
  定义数组也可以,本质上就是整型数据 

 enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
};

注意:第一个枚举成员的默认值为整型的 0,后续枚举成员的值在前一个成员上加 1。我们在这个实例中把第一个枚举成员的值定义为 1,第二个就为 2,以此类推。

enum season {spring, summer=3, autumn, winter};

没有指定值的枚举元素,其值为前一元素加 1。也就说 spring 的值为 0,summer 的值为 3,autumn 的值为 4,winter 的值为 5。

union MyUnion {
    int i;
    float f;
    char c;
};
union MyUnion u;

u.i = 42;         // 将整数 42 存储在共用体中
printf("%d\n", u.i);  // 输出 42

u.f = 3.14;       // 将浮点数 3.14 存储在共用体中
printf("%f\n", u.f);  // 输出 3.14

u.c = 'A';        // 将字符 'A' 存储在共用体中
printf("%c\n", u.c);  // 输出 'A'
#include 
#include 
int main()
{

    enum color { red=1, green, blue };

    enum  color favorite_color;

    /* ask user to choose color */
    printf("请输入你喜欢的颜色: (1. red, 2. green, 3. blue): ");
    scanf("%d", &favorite_color);

    /* 输出结果 */
    switch (favorite_color)
    {
    case red:
        printf("你喜欢的颜色是红色");
        break;
    case green:
        printf("你喜欢的颜色是绿色");
        break;
    case blue:
        printf("你喜欢的颜色是蓝色");
        break;
    default:
        printf("你没有选择你喜欢的颜色");
    }

    return 0;
}

 请输入你喜欢的颜色: (1. red, 2. green, 3. blue): 1
你喜欢的颜色是红色 

你可能感兴趣的:(学习,笔记)