C语言学习之路(基础篇)—— 复合类型(自定义类型)

news2024/11/30 12:45:48

说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!

结构体

1) 概述

数组:描述一组具有相同类型数据的有序集合,用于处理大量相同类型的数据运算。

结构体:将多个相同或不同类型的数据存在在一块连续的内存空间中。

有时我们需要将不同类型的数据组合成一个有机的整体,如:一个学生有学号/姓名/性别/年龄/地址等属性。显然单独定义以上变量比较繁琐,数据不便于管理。

语言中给出了另一种构造数据类型——结构体。
在这里插入图片描述

2) 结构体变量的定义和初始化

定义结构体变量的方式:

  • 先声明结构体类型再定义变量名
  • 在声明类型的同时定义变量
  • 直接定义结构体类型变量(无类型名)

在这里插入图片描述

结构体类型和结构体变量关系:

  • 结构体类型:指定了一个结构体类型,它相当于一个模型,但其中并无具体数据,系统对之也不分配实际内存单元。
  • 结构体变量:系统根据结构体类型(内部成员状况)为之分配空间。

示例1:定义一个结构体数据类型

// 定义一个结构体数据类型
// 关键字 struct 代表这个是一个结构体类型,
// stu   是这个结构的名字
// 整个结构体的类型是   struct  stu
// 结构体类型struct  stu   {}中是结构体的成员,一个有3个成员,每个成员的类型可以是
// 任意的类型
// 定义结构体类型时,{}后面记得加分号
// 注意定义结构struct  stu,它只是一个类型,一个模板,没有空间,不可以给结构体成员赋值
struct stu
{
	int id;
	int age;
	char name[128];
}; 
int main()
{

	return 0;
}

示例2:定义结构体变量

// 第一种常用定义方式
struct stu
{
	int id;
	int age;
	char name[128];
}a; //定义类型时,同时定义了一个结构体变量,相当于struct  stu a;

struct stu2
{
	int id;
	int age;
	char name[128];
}a,b; //定义类型时,同时定义了两个结构体变量,相当于struct  stu a,b;
// 第二种常用定义方式(用的最多)
struct stu
{
	int id;
	int age;
	char name[128];
};
struct  stu c;
int main()
{

	return 0;
}
// 第三种常用定义方式(用的很少)
struct
{
	int id;
	int age;
	char name[128];
}a;

示例3:结构体变量的初始化

//结构体类型的定义
struct stu
{	
	int id;
	int age;
	char name[128];
};

//先定义类型,再定义变量(常用)
struct stu s1 = { 1, 18, "cdtaogang" };


//定义类型同时定义变量
struct stu2
{	
	int id;
	int age;
	char name[128];
}s2 = { .age=22 }; // 给部分成员初始化,其他成员内容为0

struct
{	
	int id;
	int age;
	char name[128];
}s3 = { "yuri", 25 };

3) 结构体成员的使用

示例1:通过结构体变量操作结构体成员,使用点域.操作

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

// 定义一个结构体数据类型
struct stu
{
	int id;
	int age;
	char name[128];
}a; //定义类型时,同时定义了一个结构体变量,相当于struct  stu a;
struct  stu b;
int main()
{	
	//struct  stu c = {1,20,"cdtaogang"};
	//struct  stu c = { .age=20 };//给部分成员初始化,其他成员内容为0
	struct  stu d;
	//如何给结构体成员赋值(如何操作结构体成员)
	//通过结构体变量操作结构体成员,使用点域.操作
	d.id = 2;
	d.age = 20;
	//d.name = "cdtaogang"; // error 数组名是一个常量,不能被赋值
	strcpy(d.name , "cdtaogang"); 
	printf("%d %d %s\n",d.id,d.age,d.name);
	return 0;
}

示例2:通过结构体的地址操作结构体成员,使用指向->操作

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

// 定义一个结构体数据类型
struct stu
{
	int id;
	int age;
	char name[128];
}a; //定义类型时,同时定义了一个结构体变量,相当于struct  stu a;
struct  stu b;
int main()
{	
	struct  stu d;
	// 通过结构体的地址操作结构体成员,使用->
	(&d)->id = 3;
	(&d)->age = 21;
	strcpy((&d)->name, "cdtaogang");
	printf("%d %d %s\n", (&d)->id, (&d)->age, (&d)->name);
	return 0;
}

在这里插入图片描述

4) 结构体数组

结构体数组:是一个数组,数组的每一个元素都是结构体

在这里插入图片描述

示例:定义一个结构体数组

#include <stdio.h>


struct stu
{	
	int id;
	int age;
	char name[128];
};

int main()
{	
	// 定义一个结构体数组,结构体数组有5个元素,每个元素是struct stu类型
	struct stu data[5] = { {1,20,"laowang"},{2,21,"lihao"},{3,22,"cdtaogang"},{4,23,"zhaoqiang"},{5,24,"wangwu"} };
	
	for (int i = 0; i < sizeof(data)/sizeof(data[0]); i++)
	{
		printf("%d %d %s\n", data[i].id, data[i].age, data[i].name);
	}
	
	return 0;
}
输出结果
1 20 laowang
2 21 lihao
3 22 cdtaogang
4 23 zhaoqiang
5 24 wangwu

案例:统计学生成绩

#include <stdio.h>

//统计学生成绩
struct stu2
{
	int num;
	char name[20];
	char sex;
	float score;
};

int main()
{
	//定义一个含有5个元素的结构体数组并将其初始化
	struct stu2 boy[5] = {
		{ 101, "Li ping", 'M', 45 },
		{ 102, "Zhang ping", 'M', 62.5 },
		{ 103, "He fang", 'F', 92.5 },
		{ 104, "Cheng ling", 'F', 87 },
		{ 105, "Wang ming", 'M', 58 } };

	int i = 0;
	int c = 0;
	float ave, s = 0;
	for (i = 0; i < 5; i++)
	{
		s += boy[i].score;	//计算总分
		if (boy[i].score < 60)
		{
			c += 1;		//统计不及格人的分数
		}
	}

	printf("s=%f\n", s);//打印总分数
	ave = s / 5;					//计算平均分数
	printf("average=%f\ncount=%d\n\n", ave, c); //打印平均分与不及格人数

	for (i = 0; i < 5; i++)
	{
		printf(" name=%s,  score=%f\n", boy[i].name, boy[i].score);
		// printf(" name=%s,  score=%f\n", (boy+i)->name, (boy+i)->score);
	}

	return 0;
}

在这里插入图片描述

5) 结构体套结构体

示例:结构体套结构体

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

struct stu
{
	int id;
	int age;
	char name[128];
};

struct cls_stu
{
	/*int id;
	int age;
	char name[128];*/
	struct stu s;
	char subject[128];
};

int main()
{
	struct cls_stu cs;
	cs.s.id = 1;
	cs.s.age = 20;
	strcpy(cs.s.name, "cdtaogang");
	strcpy(cs.subject, "c/c++");
	printf("id=%d, age=%d, name=%s, subject=%s", cs.s.id, cs.s.age, cs.s.name, cs.subject);

	return 0;
}
输出结果
id=1, age=20, name=cdtaogang, subject=c/c++

6) 结构体赋值

示例1:第一种方法

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>


struct stu
{
	int id;
	int age;
	char name[128];
};

void memcpy_str(struct stu *x, struct stu* y)
{
	memcpy(x, y, sizeof(*x));

}

int main()
{
	struct stu a;
	struct stu b = { 1, 22, "cdtaogang" };
	//memcpy(&a, &b, sizeof(a));
	memcpy_str(&a, &b); //将上面改为函数调用实现形参改变实参的值
	printf("%d %d %s\n", a.id, a.age, a.name);

	return 0;
}

示例2:第二种方法

int main()
{
	struct stu a;
	struct stu b = { 1, 22, "cdtaogang" };
	// 第一种方法
	//memcpy(&a, &b, sizeof(a));
	//memcpy_str(&a, &b);
	// 第二种方法
	a.id = b.id;
	a.age = b.age;
	strcpy(a.name, b.name);
	printf("%d %d %s\n", a.id, a.age, a.name);

	return 0;
}

示例3:第三种方法

int main()
{
	struct stu a;
	struct stu b = { 1, 22, "cdtaogang" };
	// 第一种方法
	//memcpy(&a, &b, sizeof(a));
	//memcpy_str(&a, &b);
	// 第二种方法
	/*a.id = b.id;
	a.age = b.age;
	strcpy(a.name, b.name);*/
	// 第三种方法
	// a = b 内核实现的原理就是memcpy(&a, &b, sizeof(a));
	a = b; // 相同类型的变量是可以相互赋值
	printf("%d %d %s\n", a.id, a.age, a.name);

	return 0;
}

在这里插入图片描述

7) 结构体和指针*

7.1 指向普通结构体变量的指针

示例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


struct stu
{
	int id;
	int age;
	char name[128];
};

int main()
{
	//struct stu* p; // error 野指针 没有初始化,指向随机
	// 第一种方式
	struct stu s;
	struct stu* p = &s;
	(*p).id = 1;
	(*p).age = 20;
	strcpy((*p).name,"cdtaogang");

	printf("(*p).id=%d, (*p).age=%d, (*p).name=%s", (*p).id, (*p).age, (*p).name);

	return 0;
}
输出结果
(*p).id=1, (*p).age=20, (*p).name=cdtaogang

7.2 堆区结构体变量

示例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


struct stu
{
	int id;
	int age;
	char name[128];
};

int main()
{
	//struct stu* p; // error 野指针 没有初始化,指向随机
	// 第一种方式
	/*struct stu s;
	struct stu* p = &s;*/
	// 第二种方式
	struct stu* p = malloc(sizeof(struct stu));
	p->id = 1;
	p->age = 20;
	strcpy(p->name, "cdtaogang");

	printf("p->id=%d, p->age=%d, p->name%s\n", p->id, p->age, p->name);
	printf("(*p).id=%d, (*p).age=%d, (*p).name=%s", (*p).id, (*p).age, (*p).name);
	
	free(p);
	p = NULL;
	
	return 0;
}
输出结果
p->id=1, p->age=20, p->namecdtaogang
(*p).id=1, (*p).age=20, (*p).name=cdtaogang

在这里插入图片描述

7.3 结构体套一级指针

示例1:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


struct std
{	
	int age;
	char* name; //一级指针
};

int main() 
{
	struct std* p = (struct std*)malloc(sizeof(struct std));
	p->age = 18;
	p->name = "cdtaogang";

	printf("%d %s\n", p->age, p->name);

	return 0;
}

在这里插入图片描述

输出结果
18 cdtaogang

示例2:

struct std
{	
	int age;
	char* name; //一级指针
};

int main() 
{
	struct std* p = (struct std*)malloc(sizeof(struct std));
	p->age = 18;
	//p->name = "cdtaogang";
	strcpy(p->name, "cdtaogang"); // error 野指针 p没有指向 相当于 char *name; strcpy(name, "cdtaogang")一个道理

	printf("%d %s\n", p->age, p->name);

	return 0;
}

在这里插入图片描述

在这里插入图片描述

示例3:

struct std
{	
	int age;
	char* name; //一级指针
};

int main() 
{
	struct std* p = (struct std*)malloc(sizeof(struct std));
	p->age = 18;
	//p->name = "cdtaogang"; // ok
	p->name = (char*)malloc(128);
	strcpy(p->name, "cdtaogang"); // error 野指针 p没有指向

	printf("%d %s\n", p->age, p->name);

	return 0;
}

在这里插入图片描述

输出结果
18 cdtaogang

示例4:简化分析p->name = "cdtaogang";strcpy(p->name, "cdtaogang");两种方式,这里的name在以下示例以p来表示

// 正确示例
int main()
{
	char* p;
	p = "cdtaogang";
}

在这里插入图片描述

// 错误示例
int main()
{
	int* p;
	strcpy(p, "cdtaogang");// 将cdtaogang的内容拷贝到p所指向的空间(地址)
}

在这里插入图片描述

// 正确示例
int main()
{
	char* p;
	p = (int*)malloc(128);
	strcpy(p, "cdtaogang");// 将cdtaogang的内容拷贝到p所指向的空间(地址)
}

在这里插入图片描述

示例5:结构体套结构体一级指针

struct s
{
	int a;
};
struct std
{	
	int age;
	char* name; //一级指针
	struct s* num; // 指针需要申请开辟空间
	//struct s num2; // 变量不需要申请开辟空间
};

int main()
{
	struct std* p = (struct std*)malloc(sizeof(struct std));
	p->age = 20;

	p->name = (char*)malloc(128);
	strcpy(p->name, "cdtaogang");
	//p->num2.a = 100;  // num2是变量用.不能用->
	p->num->a = 200; // error  num是野指针,不能直接赋值给num所指向的空间

	printf("%d %s\n", p->age, p->name);

	return 0;
}

在这里插入图片描述

解决方法一样申请开辟空间即可

struct s
{
	int a;
};
struct std
{	
	int age;
	char* name; //一级指针
	struct s* num; // 指针需要申请开辟空间
	//struct s num2; // 变量不需要申请开辟空间
};

int main()
{
	struct std* p = (struct std*)malloc(sizeof(struct std));
	p->age = 20;

	p->name = (char*)malloc(128);
	strcpy(p->name, "cdtaogang");
	//p->num2.a = 100;  // num2是变量用.不能用->
	//p->num->a = 200; // error  num是野指针,不能直接赋值给num所指向的空间
	p->num = (struct s*)malloc(sizeof(struct s));
	p->num->a = 200;

	printf("%d %s %d\n", p->age, p->name, p->num->a);

	return 0;
}

在这里插入图片描述

释放空间,从里往外释放,有多少个malloc就释放free多少个(p的空间是定义的时候就有的 ,而p指向的空间是malloc之后才有的,即才有了age、name、num的空间而name和num指向的空间是malloc之后才有的

int main()
{
	struct std* p = (struct std*)malloc(sizeof(struct std));
	p->age = 20;

	p->name = (char*)malloc(128);
	strcpy(p->name, "cdtaogang");
	//p->num2.a = 100;  // num2是变量用.不能用->
	//p->num->a = 200; // error  num是野指针,不能直接赋值给num所指向的空间
	p->num = (struct s*)malloc(sizeof(struct s));
	p->num->a = 200;

	printf("%d %s %d\n", p->age, p->name, p->num->a);

	free(p->name);
	free(p->num);
	free(p);

	return 0;
}

在这里插入图片描述

8) 结构体做函数参数*

8.1 结构体普通变量做函数参数

示例:结构体普通变量做函数参数

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include <string.h>

//结构体类型的定义
struct stu
{
	char name[50];
	int age;
};

//函数参数为结构体普通变量
void set_stu(struct stu tmp)
{
	strcpy(tmp.name, "cdtaogang");
	tmp.age = 18;
	printf("tmp.name = [%s], tmp.age = [%d]\n", tmp.name, tmp.age);
}

int main()
{
	struct stu s = { 0 };
	set_stu(s); //值传递
	printf("s.name = [%s], s.age = [%d]\n", s.name, s.age);

	return 0;
输出结果
tmp.name = [cdtaogang], tmp.age = [18]
s.name = [], s.age = [0]

8.2 结构体指针变量做函数参数

示例:结构体指针变量做函数参数

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include <string.h>

//结构体类型的定义
struct stu
{
	char name[50];
	int age;
};

//函数参数为结构体指针变量
void set_stu_pro(struct stu* tmp)
{
	strcpy(tmp->name, "cdtaogang");
	tmp->age = 18;
	printf("tmp->name = [%s], tmp->age = [%d]\n", tmp->name, tmp->age);
}

int main()
{
	struct stu s = { 0 };
	set_stu_pro(&s); //地址传递
	printf("s.name = [%s], s.age = [%d]\n", s.name, s.age);

	return 0;
}
输出结果
tmp->name = [cdtaogang], tmp->age = [18]
s.name = [cdtaogang], s.age = [18]

8.3 结构体数组名做函数参数

示例:结构体数组名做函数参数

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include <string.h>


struct stu
{
	
	int id;
	char name[128];

};
//void set_tmp(struct stu tmp[5], int n)
void set_tmp(struct stu *p, int n)
{
	for (int i = 0; i < n; i++)
	{	
		// 第一种方式用点域
		(*(p + i)).id = 22;
		p[i].id = 22; // 上面的简写
		// 第二种方式用指向
		//(p + i)->id = 22;
		char buf[128];
		sprintf(buf, "%s%d", "cdtaoang", i+1);
		strcpy(p[i].name, buf);
		printf("p[%d].id = %d, p[%d].name = %s\n", i, p[i].id, i, p[i].name);
	}
}

int main()
{

	struct stu tmp[5] = { 0 };
	int n = sizeof(tmp) / sizeof(tmp[0]);
	set_tmp(tmp, n); // tmp = &tmp[0]
	printf("\n");
	for (int i = 0; i < n; i++)
	{
		printf("tmp[%d].id = %d, tmp[%d].name = %s\n", i, tmp[i].id, i, tmp[i].name);
	}

	return 0;
}

在这里插入图片描述

在这里插入图片描述

8.4 const修饰结构体指针形参变量

示例:const修饰结构体指针形参变量

#include<stdio.h>


struct stu
{
	int id;
	char name[128];
};

int main()
{
	struct stu a;
	struct stu b;
	struct stu const *p = &a;
	// p->id = 10; // error  const修饰的是*,不能通过指针p去修改p指向的那块空间里面内容(指向)

	struct stu * const p2 = &a;
	p2->id = 20; // ok
	//p2 = &b; // error const修饰的是指针变量p, 不能修改变量p本身的内容(指向)

	return 0;
}

共用体(联合体)

  • 联合union是一个能在同一个存储空间存储不同类型数据的类型;
  • 联合体所占的内存长度等于其最长成员的长度倍数,也有叫做共用体;
  • 同一内存段可以用来存放几种不同类型的成员,但每一瞬时只有一种起作用;
  • 共用体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员的值会被覆盖;
  • 共用体变量的地址和它的各成员的地址都是同一地址。

1) 共用体的定义和初始化

示例1:定义一个共用体数据类型

union test
{
	char a;
	short b;
	int c;
};

示例2:定义共用体变量,跟结构体定义方式一样

union test
{
	char a;
	short b;
	int c;
}tmp;
union test
{
	char a;
	short b;
	int c;
};
union test tmp;
union
{
	char a;
	short b;
	int c;
}tmp;

示例3:共用体变量的初始化(共用体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员的值会被覆盖

#include <stdio.h>


union test
{
	char a;
	short b;
	int c;
};

int main()
{	
	union test tmp;
	tmp.a = 0x01;
	tmp.b = 0x0a0b;
	tmp.c = 0x01020304;
	
	printf("tmp.a = %x\n", tmp.a); // 04
	printf("tmp.b = %x\n", tmp.b); // 0304
	printf("tmp.c = %x\n", tmp.c); // 01020304

	return 0;
}

在这里插入图片描述

#include <stdio.h>


union test
{
	char a;
	short b;
	int c;
};

int main()
{	
	union test tmp;
	tmp.a = 0x01;
	tmp.c = 0x01020304;
	tmp.b = 0x0a0b;
	
	printf("tmp.a = %x\n", tmp.a); // 0b
	printf("tmp.b = %x\n", tmp.b); // 0a0b
	printf("tmp.c = %x\n", tmp.c); // 01020a0b

	return 0;
}

在这里插入图片描述
示例4:共用体的大小

printf("sizeof(tmp)=%d", sizeof(tmp));  //sizeof(tmp)=4 即 sizeof(int)=4 联合体所占的内存长度等于其最长成员的长度倍数

2) 共用体判断大小端

小端: 低位存低地址,高位存高地址(大型服务器)
大端: 低位存高地址,高位存低地址(小型计算机)

在这里插入图片描述

示例:共用体判断大小端

#include <stdio.h>


union test
{
	short b;
	char buf[2];
};

int main()
{
	union test tmp;
	tmp.b = 0x0102;

	if (tmp.buf[0] == 0x01)
	{
		printf("大端\n");
	}
	else
	{
		printf("小端\n");
	}

	return 0;
}

在这里插入图片描述

输出结果
小端

枚举

枚举: 将枚举类型的变量的值一一列举出来,变量的值只限于列举出来的值的范围内。

枚举类型定义:

enum  枚举名
{
	枚举值表
};
  • 在枚举值表中应列出所有可用值,也称为枚举元素。
  • 枚举值是常量,不能在程序中用赋值语句再对它赋值。
  • 举元素本身由系统定义了一个表示序号的数值从0开始顺序定义为0,1,2 …

1) 枚举定义

示例1:为了避免需要多次定义宏,C语言提供了枚举

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#define Mon 1
#define Tue 2
#define Wed 3


int main()
{	
	int num;
	scanf("%d", &num);

	if (Mon == num)
	{
		printf("游泳\n");
	}
	else if (Tue == num)
	{
		printf("跑步\n");
	}
	else if (Wed == num)
	{
		printf("游戏\n");
	}


	return 0;
}
// 枚举定义
// 默认枚举里面的值从0开始
enum week
{
	Mon,
	Tue,
	Wed
};

int main()
{	
	printf("%d %d %d", Mon, Tue, Wed); // 0 1 2
	return 0;
}

2) 枚举赋值

示例2:枚举赋值

enum week
{
	Mon=1,
	Tue,
	Wed
};

int main()
{	
	printf("%d %d %d", Mon, Tue, Wed); // 1 2 3
	return 0;
}
enum week
{
	Mon,
	Tue=5,
	Wed
};

int main()
{	
	printf("%d %d %d", Mon, Tue, Wed); // 0 5 6
	return 0;
}

3) 定义枚举变量

示例1:先定义枚举类型,再定义枚举变量

enum week
{
	Mon,
	Tue=5,
	Wed
};

int main()
{	
	enum week day = Wed; //给枚举变量 day 赋值,值就是Wed枚举元素
	printf("%d %d %d", Mon, Tue, Wed); // 0 5 6
	return 0;
}

示例2:定义枚举类型的同时定义枚举变量

enum week
{
	Mon,
	Tue=5,
	Wed
}day;// 表示 定义了一个枚举类型 enum week,同时定义了一个变量 day(类型是 enum week)

int main()
{	
	day = Wed; //给枚举变量 day 赋值,值就是某个枚举元素
	printf("%d %d %d", Mon, Tue, Wed); // 0 5 6
	return 0;
}

示例3:省略枚举名称,直接定义枚举变量

```c
enum
{
	Mon,
	Tue=5,
	Wed
}day;//这样使用枚举,该枚举类型只能使用一次

案例:使用枚举实现#define false 0 #define true 1

#include <stdio.h>

enum weekday
{
	sun = 2, mon, tue, wed, thu, fri, sat
} ;

enum bool
{
	flase, true
};

int main()
{	
	// 先定义枚举类型,再定义枚举变量
	enum weekday a, b, c;
	a = sun;
	b = mon;
	c = tue;
	printf("%d,%d,%d\n", a, b, c);

	enum bool flag;
	flag = true;

	if (flag == 1)
	{
		printf("flag为真\n");
	}
	return 0;
}

在这里插入图片描述

typedef

typedefC语言的关键字,作用是为一种数据类型(基本类型或自定义数据类型)定义一个新名字,不能创建新类型

  • #define不同,typedef仅限于数据类型,而不是能是表达式或具体的值
  • #define发生在预处理,typedef发生在编译阶段

示例1:使用typedef起别名

#include <stdio.h>


typedef int u32;

struct stu
{
	int id;
	int age;
};
typedef struct stu ST;
int main()
{
	int a = 10;
	u32 b = 10;
	ST tmp;
	tmp.id = 2;
	tmp.age = 20;
	printf("%d %d\n", sizeof(a), sizeof(b));
	printf("%d %d\n", tmp.id, tmp.age);

	return 0;
}
输出结果
4 4
2 20

示例2:宏与typedef起别名

#include <stdio.h>
#define CHAR char
typedef char CHAR32;

int main()
{
	CHAR a;
	CHAR32 b;

	a = 10;
	b = 20;
	printf("%d %d\n", sizeof(a), sizeof(b));

	return 0;
}
输出结果
1 1

示例3:使用宏起别名存在的问题和风险

#include <stdio.h>
#define CHAR char*
typedef char* CHAR32;

int main()
{
	CHAR x, y;  // char *x,y;
	CHAR32 j, k; // char *j,*k;
	printf("%d %d\n", sizeof(x), sizeof(y));
	printf("%d %d\n", sizeof(j), sizeof(k));

	return 0;
}
输出结果
4 1
4 4

在实际编程中,取别名广泛应用,如下图所示查看VS编译器中size_t类型其实就是int类型

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/41167.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

工具分享:Springboot+Netty+Xterm搭建一个网页版的SSH终端

一. 简述 搭建一个web ssh&#xff0c;主要是借助websocket和xterm&#xff0c;可以实现一个类似于xshell的效果&#xff0c;如图&#xff1a; 二. 技术栈 这里使用了springboot、netty、jsch、react、Ts,xterm。 这里我用了springboot和netty实现了websocket&#xff0c;js…

稳了,我用 Python 可视化分析和预测了 2022 年 FIFA 世界杯

许多人称足球为 “不可预测的游戏”&#xff0c;因为一场足球比赛有太多不同的因素可以改变最后的比分。 预测一场比赛的最终比分或赢家确实是很难的&#xff0c;但在预测一项比赛的赢家时就不是这样了。在过去的5年中&#xff0c;Bayern Munich 赢得了所有的德甲联赛&#xf…

如何发布一个属于自己的 npm 包

如何发布一个属于自己的 npm 包 start 在日常的工作中&#xff0c;我们会接触很多 npm 包。 例如&#xff1a; npm install jquerynpm install vue/clinpm install axios# ... 等等有时候会想到&#xff0c;构建一个属于自己的 npm 包&#xff0c;应该超级酷吧&#xff1f; …

zabbix基础环境部署

目录 一、环境准备 二、部署LNMP 1、安装Nginx及其依赖包 2、修改nginx配置 3、测试页面 三、部署zabbix服务端 1、下载zabbix 2、安装源码zabbix 3、为zabbix创建数据库与数据库账户 4、搭建Zabbix页面 4.1、第1步 Check of pre-requisites 4.2、第2步 Configure D…

Python代码的编写运行方式

Python代码的编写运行方式介绍 python官方运行环境可到网站https://www.python.org/downloads/找到合适版本下载安装。 安装比较容易&#xff0c;特别强调&#xff0c;安装过程建议勾选“Add Python to PATH”&#xff08;将Python添加到PATH环境变量&#xff09;【注1】&…

Docker安装Minio

寻找Minio镜像 Docker Hub 查找官方镜像 下载Minio镜像 下载最新版Minio镜像 docker pull minio/minio等同于 docker pull minio/minio:latest下载指定版本的Minio镜像 docker pull minio/minio:RELEASE.2022-11-26T22-43-32Z.fips检查当前所有Docker下载的镜像 docker …

第六章TCP/IP——网络传输硬件设备

个人简介&#xff1a;云计算网络运维专业人员&#xff0c;了解运维知识&#xff0c;掌握TCP/IP协议&#xff0c;每天分享网络运维知识与技能。个人爱好: 编程&#xff0c;打篮球&#xff0c;计算机知识个人名言&#xff1a;海不辞水&#xff0c;故能成其大&#xff1b;山不辞石…

Linux进程通信之消息队列

目录 1.消息队列的原理&#xff1a; 2.消息队列的接口&#xff1a; &#xff08;1&#xff09;创建消息队列 &#xff08;2&#xff09;向消息队列发送消息 &#xff08;3&#xff09;接收消息 &#xff08;4&#xff09;操作消息队列的接口 1.消息队列的原理&#xff1a; 消…

docker 安装 Heimdall 导航页

前言 随着群晖中使用的功能越来越多&#xff0c;各种端口太多容易忘&#xff0c;所以就有了使用导航页的想法&#xff08;使用收藏夹的朋友除外&#xff09;。群晖也有自带的WEB套件管理&#xff0c;不过个人感觉相对麻烦&#xff0c;使用 Heimdall 导航页可以设置密码登录&am…

【数字信号调制】16QAM信号调制解调【含Matlab源码 2050期】

⛄一、QAM调制与解调&#xff08;附实验题目说明&#xff09; 1 引 言 数字振幅调制、数字频率调制和数字相位调制是数字调制的基础,然而,这3种数字调制方式都存在不足之处。如频谱利用率低、抗多径衰落能力差、功率谱衰减慢、带外辐射严重等。为了改善这些不足,几十年来人们不…

yocto machine class解析之st-partitions-image

yocto machine class解析之st-partitions-image stm32mp157 yocto的meta-st-stm32mp layer中提供了几个class,后续几篇文章重点分析这些class文件&#xff1a; 第一篇就从st-partitions-image.bbclass 开始&#xff0c;st所有创建image的bb文件都会引用st-partitions-image&am…

「UWB」精准定位黑科技,开启座舱雷达新蓝海

基于厘米级定位、超低功率、强抗干扰、超大容量等技术特点&#xff0c;UWB&#xff08;超宽带&#xff09;技术在消费电子、智能汽车等领域的应用前景被赋予厚望。 值得一提的是&#xff0c;利用UWB雷达还可实现舱内活体检测、脚踢尾箱等&#xff0c;这意味着新一轮座舱感知革…

【Vue】ref引用,插槽

一、ref 什么是ref&#xff1f; ref用来辅助开发者在不依赖于jQuery 的情况下&#xff0c;获取DOM元素或组件的引用。 每个vue的组件实例上&#xff0c;都包含一个$refs对象&#xff0c;里面存储着对应的DOM元素或组件的引用。默认情况下&#xff0c;组件的$refs 指向一个空对…

Ubuntu20.04下安装nvidia驱动

ubuntu-drivers devices会显示你的电脑上可用的nvidia驱动。只需要安装推荐的版本即可&#xff08;后面有recommend字样&#xff09; 打开电脑里的软件和更新app&#xff08;这里建议换提前换源&#xff0c;阿里源或者清华源&#xff09; 来到附加驱动这个页面&#xff0c;选…

HTML初识-概念和基本知识

1 . HTML初识-基础认知 HTML标签 1.1 目录 ◆ 基础认知 ◆ HTML标签学习 ◆ 综合案例 1.2 学习目标 ◆ 能够理解HTML的 基本语法 和标签的关系 ◆ 能够使用 排版标签 实现网页中标题、段落等效果 ◆ 能够使用 相对路径 选择不同目录下的文件 ◆ 能够使用 媒体标签 在网页中显示…

ES进阶教程

1.分片Shards 一个索引可以存储超出单个结点硬件限制的大量数据,es提供了将索引划分为多份的能力,每一份都称之为分片.当创建索引时,可以指定想要的分片数量.每个分片本身也是一个功能完善并且相对独立的索引.这个索引可以被放在集群中的任何结点上. 分片的重要性 1.允许水平切…

相控阵天线(九):平面阵列天线综合(不可分离型切比雪夫分布、圆口径泰勒综合、可分离型分布、配相抵消法)

目录简介不可分离型分布不可分离型切比雪夫圆口径泰勒综合可分离型分布可分离切比雪夫综合可分离泰勒综合平面阵列配相抵消法简介 按行、列排列的可分离型矩形平面阵&#xff0c;其阵因子是两个正交排列的直线阵阵因子的乘积。可分离的平面阵方向图在两个主面内是满足预期副瓣…

Docker创建Spring容器【方便服务迁移】

&#x1f4c3;目录跳转&#x1f4da;简介&#xff1a;&#x1f383; 1.上传jar包&#x1f389;2.创建Dockerfile文件&#x1f5fa;️3.生成容器&#x1f365;4.查看本地镜像&#x1f680;5.运行镜像&#x1f52d;6.使用工具访问接口&#x1f3c6;总结&#x1f4da;简介&#xf…

网上预约挂号系统的设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

si9000 单端(线)差分(动)线板层结构与阻抗计算

常见的单端(线)阻抗计算模式&#xff1a; Surface Microstrip 1B 在下图(表面&#xff0c;或暴露&#xff0c;微带)信号线暴露(空气)和参考电源或接地平面。根据电介质相对于迹的排列(在迹的下方或上方)对结构进行分类。下图显示了在信号轨迹(指定为1B)以下使用单一介电层的表…