C语言提高 (5) 第五天 结构体,结构体对齐 文件
1昨日回顾
2作业讲解
3 结构体的基本定义
//1
struct teacher
{
int id;
char name[64];
};
struct teacher t5 = { 5, "laoshi5" };
//2
struct {
int id;
char name[64];
} t3, t4;//匿名的结构体类型 类型只能定义一次, 不能通过函数传参
//3
typedef struct _teacher
{
int id;
char name[64];
} teacher_t; //最常用的写法
/*
struct _teacher
{
int id;
char name[64];
};
typedef struct _teacher teacher_t;
*/
void print_teacher(struct teacher* p1)
{
printf("id = %d\n", p1->id);
printf("name = %s\n", p1->name);
}
void print_teacher2(struct teacher t) //t = t1 int a = b; struct teacher t1 = t2
{
printf("===== print_teacher2===\n");
printf("id = %d\n", t.id);
printf("name = %d\n", t.name);
}
void copy(struct teacher to, struct teacher from)
{
to = from;
}
void copy2(struct teacher *to, struct teacher *from)
{
*to = *from;
}
/*
void print_teacher2(struct {
int id;
char name[64];
})
*/
int main(void)
{
struct teacher t1;
struct teacher t8;
teacher_t t6 = {6, "laoshi6"};
//teacher t7; // C语言中 定义一个结构体 必须加上struct 关键字 C++不用加
t1.id = 10;
strcpy(t1.name, "laoshi1");
print_teacher(&t1);
print_teacher(&t5);
print_teacher2(t1); //
printf("=====\n");
copy2(&t8, &t1);
print_teacher(&t8);
struct teacher t9 = t1; //int a = b;
return 0;
}
4 结构体作为函数参数
5结构体嵌套一级指针
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME_LEN (64)
struct teacher
{
int id;
char *name;
};
int create_teachers(struct teacher **tpp, int num)
{
if (tpp == NULL) return;
struct teacher *tp;
int i = 0;
// 在堆上分配空间
tp = (struct teacher*) malloc(sizeof(struct teacher)* num);
if (tp == NULL)
{
fprintf(stderr, "malloc tp error\n");
return -1;
}
memset(tp, 0, sizeof(struct teacher) * num);
for (i = 0; i < num; i++)
{
// 在堆上给name分配空间
tp[i].name = (char *)malloc(sizeof(char)*NAME_LEN);
memset(tp[i].name, 0, sizeof(char)*NAME_LEN);
}
// 开辟完之后把指针传出去
*tpp = tp;
return 0;
}
void sort_teacher(struct teacher *tp,int num)
{
int i = 0;
int j = 0;
struct teacher temp_teacher;
for (i = 0;i<num-1;i++)
{
for (j = i; j < num; j++)
{
// 每次把最小的放到数组最开始的位置
if (tp[i].id > tp[j].id) {
temp_teacher = tp[i];
tp[i] = tp[j];
tp[j] = temp_teacher;
}
}
}
}
void print_teacher(struct teacher* p, int num)
{
int i = 0;
for (i = 0; i < num; i++)
{
printf("=========\n");
printf("id:%d\n", p[i].id);
printf("name:%s\n", p[i].name);
}
}
// 内存释放
void free_teachers(struct teacher **tpp,int num)
{
if (tpp == NULL)
{
return;
}
struct teacher *tp = *tpp;
int i = 0;
if (tp != NULL)
{
for (i = 0; i < num; i++) {
if (tp[i].name != NULL)
{
free(tp[i].name);
tp[i].name = NULL;
}
}
free(tp);
*tpp = NULL;
printf("free success\n");
}
}
int main(int argc,char* argv[])
{
// 创建两个老师
// 创建结构体指针
struct teacher *tp = NULL;
int num = 2;
int i = 0;
int ret = 0;
// 传入指针,通过二级指针接收来对此指针所指向内存区域进行修改
ret = create_teachers(&tp, num);
if (ret < 0) return -1;
// 为堆上的name的位置赋值
for (i = 0; i < num; i++)
{
printf("enter tp[%d]'s id :", i);
scanf("%d", &tp[i].id);
printf("enter tp[%d]'s name :", i);
scanf("%s", tp[i].name);
}
print_teacher(tp, num);
sort_teacher(tp, num);
print_teacher(tp, num);
free_teachers(&tp, num);
return 0;
}
6结构体深拷贝和浅拷贝问题
// 结构体可以通过变量直接赋值,但不要使用这种方法
// 要给结构体中的成员 一个一个的拷贝
如果结构体中有指针,浅拷贝后可能会造成重复释放的问题
7结构体内部成员的偏移量
偏移:
8中午回顾
9结构体嵌套二级指针开辟内存空间
10结构体嵌套二级指针释放空间
11结构体字节对齐
举个例子:
1 2 3 4 5 6 |
struct { char a; //1byte int b; //4byte char c[2] //2byte double d; //8byte }Struct_A; |
在计算机内存中,结构体变量的存储通常是按字长对齐的,比如8位机里就按字节对齐,那么上述结构体共占用1+4+2+8=15byte。
在16位机里,变量就按照2字节对齐,比如a这个成员,虽然是个char类型,地址在0x80000000本身只占1字节,但是下一个成员b却不能使用0x80000001这个地址,而必须使用0x80000002,这就是按字长对齐。以上结构体占用的空间也就是2+4+2+8=16字节
同理,在32位机中,如果a在0x80000000的话,b只能放在0x80000004,因为这里的字长是4个字节。以上结构体占用空间4+4+4+8=20字节
也就是说总有一些字节是浪费掉的,这样做的目的很简单,就是因为在大多数计算机体系结构中,对内存操作时按整字存取才能达到最高效率,相当于是以空间换取时间。当然在某些计算机体系结构中,比如ARM,是支持非对齐字传输的,也就是说变量并不一定要按照字长对齐,尽管这样可能会降低效率,但换来的是存储空间上的节约。对于程序员来讲,则需要将结构体声明为紧凑型结构体。声明的关键字依编译器不同而异,你可以去查一下__packed关键字,可以得到更详细的说明。使用紧凑型结构体,则会强制编译器将结构体成员按1字节对齐,则以上结构体占用空间仍为15字节。
资料:
https://bbs.csdn.net/topics/392057821
12不完整类型字节序对齐
13位移操作符
14掩码
~按位取反运算符
题目:从八位开始找四位。。。这个函数实现
0按位取反编程全1 然后向左偏移n位 然后再全部取反 与 源数据x向右偏移position位 相与
?
9.文件的操作
mysql oracle 存到硬盘中的数据库
redis mongodb 内存型数据库
(缓冲区满了以后刷新缓冲区,存到文件中
cpu在不同进程间不停切换 ,如果没有缓冲区 cpu直接把100k放到磁盘中,然后切换进程2 然后切换进程1
现在有了缓冲区,cpu可以先把100k放到内存中(很快),然后就可以去切换进程2,后面让内存与磁盘进行交互io 效率提升
文件结构体:
操作系统通过限制文件描述符fd的数目来限制打开文件的个数
standard C I/O
fputc:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define FILE_NAME "C:/Users/lg/Desktop/1.txt"
// 字符的写操作
void test_write_char()
{
char *buf = "abcdefghij";
int i = 0;
FILE *fp = fopen(FILE_NAME, "w+");
if (fp == NULL) {
fprintf(stderr, "open %s error \n", FILE_NAME);
return -1;
}
for (i = 0; i < (int)strlen(buf); i++)
{
if (fputc(buf[i], fp) == EOF) {
fprintf(stderr, "fput %c error\n", buf[i]);
break;
}
}
if (fp != NULL)
{
fclose(fp);
}
return 0;
}
int test_read_char()
{
FILE *fp = NULL;
char buf[128] = { 0 };
char ch = 0;
int i = 0;
fp = fopen(FILE_NAME, "r+");
if (fp == NULL)
{
fprintf(stderr, "fopen %s error\n",FILE_NAME);
}
while ( (ch = fgetc(fp)) != EOF)
{
buf[i] = ch;
i++;
}
printf("buf:%s\n",buf);
if (fp != NULL)
{
fclose(fp);
}
return 0;
}
int main(void)
{
test_write_char();
test_read_char();
return 0;
}
fputs fgets: 操作str
fputs不会把’\n’写进去
注意:1.fputs不会把字符串的\0写进去
2.fputs不会写\n
注意:fgets不是根据\0来从文件区分一行,而是通过\n,并会把\n读进去
总结一下:
int fputc(ch,fp) (返回值是字符ascii码)
int fgetc(fp) (返回值是字符ascii 码)
int fputs(buf,fp)
char * fgets(buf,len,fp)
文件的随机存取操作
ftell
fseek
配置文件的测试框架
多文件形式编程
配置文件的写配置实现
C语言提高 (5) 第五天 结构体,结构体对齐 文件的更多相关文章
- C语言第五次作业——循环结构
C语言程序设计第五次作业--循环结构(1) (一)改错题 输出华氏摄氏温度转换表:输入两个整数lower和upper,输出一张华氏摄氏温度转换表,华氏温度的取值范围是{lower,upper},每次增 ...
- C语言之结构体内存的对齐
C语言之结构体内存的对齐 大纲: 零.引例 一.结构体内存对齐规则 二.怎样计算结构体的大小 三.设计结构体时要注意的方面 四.为什么存在内存对齐 五.修改默认对齐数 在前面的章节中,我们谈到了C ...
- GO语言的进阶之路-go的程序结构以及包简介
GO语言的进阶之路-go的程序结构以及包简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.编辑,编译和运行 A,编辑 Go程序使用UTF-8编码的纯Unicode文本编写.大 ...
- C语言结构体的内存对齐问题
在C语言开发当中会遇到这样的情况: #include <stdio.h> struct test { int a; char b; }; int main(int argc, const ...
- C语言实现GBK/GB2312/五大码之间的转换(转)
源:C语言实现GBK/GB2312/五大码之间的转换 //----------------------------------------------------------------------- ...
- C语言高级-结构,共用体,文件,链表
C语言结构 标准声明方式 struct student{ int age; char sex; }; 这个可以在main函数中定义: struct student ...
- C语言结构体的字节对齐原则
为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据 ...
- C语言高速入门系列(五)
C语言高速入门系列(五) C语言指针初涉 ------转载请注明出处:coder-pig 本节引言: 上一节我们对C ...
- C语言实现使用动态数组来构造栈结构
我在面前一篇博客<C语言实现使用静态数组来构造栈结构>中使用了静态数组来模拟栈的操作.静态数组的大小是在代码中写死的.是存储在用户栈上面的,使用起来不灵活.在这篇博客中我会使用动态数组来构 ...
随机推荐
- DJANGO之自定义模板过滤器
我查找了DJANGO模板的过滤器,好像指定字符串包含指定关-键字符的过滤器没有呢, 没有硬着头-皮,按网上其它人的作法,写了一个,成功了...:) 参考URL: http://liuzhijun.it ...
- ios自己定义类(UIView)代码生成简单的UITableViewCell
因为一个项目中有大量的UITableViewCell须要书写,样式几乎相同都是 文字介绍:显示内容 这种. 自己又懒得写UITableViewCell类嫌不是必需:在方法tableView:cellF ...
- 新手git: ssh: connect to host localhost port 22: Connection refused
由于gitlab上要git pull或者git clone,可是每次都出现这个问题.之前偶尔出现这个问题.可是仅仅是偶尔.这是为什么呢?然后就開始搜索网上的解决方式了. 这个问题搜索网上非常多答案.可 ...
- SICP 习题1.16-1.19体会
首先反思一下, 昨天做1.14的时候犯了一个严重错误.思维定式了,导致花了非常多无用功. 1.14的关键是要想到2个物理意义. 一个是广度优先, 也就是仅仅考虑问题递归树的第一层子数.那么必定有公式 ...
- Android 四大组件学习之ContentProvider二
上节学习了什么是ContentProvider.以及ContentProvider的作用.以及什么是URL.本节就对上节学习的知识做一个实践,也就是定义自己的ContentProvider 好.实践是 ...
- luogu2761 软件补丁问题 状态压缩最短路径
关键词:状态压缩 最短路径 想不出快速办法,就先考虑考虑暴力.枚举每一种错误分布的情况,然后通过可用的补丁转化为另多种情况,这些情况又转化为更多种情况……我们可以用图来表示这种关系! 状态压缩:每个错 ...
- hdoj--1151--Air Raid(最大独立集)
Air Raid Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- hdoj--2509--Be the Winner(尼姆博弈)
Be the Winner Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
- [IOI 2008] Island
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1791 [算法] 不难看出,要求的是这个基环树森林中每棵基环树的直径之和 [代码] # ...
- vue项目中阻止浏览器返回上一页
vue项目中在某个页面阻止浏览器返回上一页,适用移动端.PC端. 使用场景例如: 首页 与 A页面 来回跳转,那样点击浏览器返回时也会来回跳转,本想当页面在首页的时候就不再返回了,所以这个时候 ...