[TOC]
字符串拷贝用strcpy,字符用=就可以了,因为=拷贝字符串时候只会拷贝首地址(第一个字符),而strcpy是把字符串里每个字符一个一个拷贝过去
结构体名字用.
结构体指针用->
# 定义
~~~
struct students {
//成员列表
char name[21];
unsigned int age;
char tel[16];
float scores[3];
char sex;
}stu = {"尼古拉斯", 500, "15557105721", 100.0f, 200, 300, 'M'};
int main() {
//按照结构体顺序赋值
// struct students stu = {"尼古拉斯", 500, "15557105721", 100.0f, 200, 300, 'M'};
//每个属性赋值
// struct students stu = {.sex = 'M', .name = "刘能", .tel = "15557105722", .scores[0] = 100, .scores[1] = 11, .scores[2] = 33, .age = 12};
//起别名赋值
// struct students stu;
// //字符串需要拷贝进去,因为需要的是个数组,给字符串的话,就把地址给过去了
// strcpy(stu.name, "abc");
// stu.age = 11;
// strcpy(stu.tel, "15557125722");
// stu.scores[0] = 100;
// stu.scores[1] = 11;
// stu.scores[2] = 33;
//别名在struct起好了
// strcpy(stu.name, "abc");
// stu.age = 11;
// strcpy(stu.tel, "15557125722");
// stu.scores[0] = 100;
// stu.scores[1] = 11;
// stu.scores[2] = 33;
printf("姓名: %s\n", stu.name);
printf("年龄: %d\n", stu.age);
printf("电话: %s\n", stu.tel);
printf("成绩: %.1f %.1f %.1f\n", stu.scores[0], stu.scores[1], stu.scores[2]);
printf("性别: %s\n", stu.sex == 'M' ? "男" : "女");
getchar();
return EXIT_SUCCESS;
}
~~~
# 结构体大小
结构体存储,内存对齐
~~~
struct students {
//成员列表
char name[21];
unsigned int age;
char tel[16];
float scores[3];
char sex;
} stu = {"尼古拉斯", 500, "15557105721", 100.0f, 200, 300, 'M'}, stu1 = {"abc", 50, "15557105721", 100.0f, 200, 300, 'M'};
int main() {
printf("%d\n", sizeof(stu1));
getchar();
return EXIT_SUCCESS;
}
~~~
# 结构体数组
~~~
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct students {
//成员列表
char name[21];
unsigned int age;
char tel[16];
float scores[3];
char sex;
};
int main() {
struct students s[2];
for (int i = 0; i < 2; ++i) {
printf("请输入\n");
scanf("%s%d%s%f%f%f%c", s[i].name, &s[i].age, s[i].tel, &s[i].scores[0],
&s[i].scores[1], &s[i].scores[2], &s[i].sex);
}
for (int j = 0; j < 2; ++j) {
printf("姓名: %s\n", s[j].name);
printf("年龄: %d\n", s[j].age);
printf("电话: %s\n", s[j].tel);
printf("成绩: %.1f %.1f %.1f\n", s[j].scores[0], s[j].scores[1], s[j].scores[2]);
printf("性别: %s\n", s[j].sex == 'M' ? "男" : "女");
printf("----------------\n");
}
getchar();
return 0;
}
~~~
# 结构体和指针
**属性指针**
~~~
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct stuinfo {
char * name;
int age;
};
int main() {
struct stuinfo si;
si.name = (char *)malloc(sizeof(char) * 21);
strcpy(si.name, "张三");
si.age = 18;
printf("%s %d\n", si.name, si.age);
free(si.name);
getchar();
return 0;
}
~~~
**指针指向结构体地址**
~~~
struct sinfo {
char * name;
int age;
}stu;
int main() {
struct sinfo * s = &stu;
s->name = (char *)malloc(sizeof(char) * 21);
strcpy(s->name, "abc");
s->age = 11;
printf("%s %d\n", s->name, s->age);
free(s->name);
getchar();
return 0;
}
~~~
**指针指向分配的空间**
~~~
struct tec {
char * name;
int age;
}t;
int main() {
struct tec * p = (struct tec *)malloc(sizeof(t));
p->name = (char *)malloc(sizeof(char) * 21);
strcpy(p->name, "abc");
p->age = 121;
printf("%s %d\n", p->name, p->age);
if (p->name != NULL) {
free(p->name);
p->name = NULL;
}
if (p) {
free(p);
p = NULL;
}
getchar();
return 0;
}
~~~
# 结构体嵌套
~~~
struct stra
{
int a;
float b;
char c;
}abc;
struct strb
{
struct stra abc;
char * e;
short f;
double d;
};
int main() {
struct strb strbb;
strbb.d = 10.0f;
strbb.abc.a = 100;
printf("%d\n", strbb.abc.a);
getchar();
return 0;
}
~~~
# 结构体指针偏移
~~~
struct Person {
char a;
int b;
char c;
int d;
};
int main() {
struct Person p = {'a', 100, 'b', 200};
printf("%d\n", sizeof(p)); //16
//2个相同,16-4就是p.d的地址
printf("%d\n", (char *) &p + 12);
printf("%d\n", &(p.d));
return 0;
}
~~~
# 堆上和栈上分配空间
~~~
//堆上分配空间
struct Person *p1 = (Person *) malloc(sizeof(struct Person));
strcpy(p1->name, "abc");
p1->age = 11;
printf("name: %s, Age: %d\n", p1->name, p1->age);
//栈上分配结构体空间
struct Person persons[] = {
{"aaa", 123},
{"bbb", 456},
{"ccc", 789},
{"ddd", 101112},
{"eee", 131415}
};
int len = sizeof(Person) / sizeof(struct Person);
~~~
# 结构体赋值
如果结构体内部有指针,并且指针指向堆空间.
那么如果发生赋值行为,就会产生2个问题
1. 同一个空间被释放2次
2. 内存泄露
所以不要直接=,如果内部有指针,自己按个赋值拷贝

- c语言
- 基础知识
- 变量和常量
- 宏定义和预处理
- 随机数
- register变量
- errno全局变量
- 静态变量
- 类型
- 数组
- 类型转换
- vs中c4996错误
- 数据类型和长度
- 二进制数,八进制数和十六进制数
- 位域
- typedef定义类型
- 函数和编译
- 函数调用惯例
- 函数进栈和出栈
- 函数
- 编译
- sizeof
- main函数接收参数
- 宏函数
- 目标文件和可执行文件有什么
- 强符号和弱符号
- 什么是链接
- 符号
- 强引用和弱引用
- 字符串处理函数
- sscanf
- 查找子字符串
- 字符串指针
- qt
- MFC
- 指针
- 简介
- 指针详解
- 案例
- 指针数组
- 偏移量
- 间接赋值
- 易错点
- 二级指针
- 结构体指针
- 字节对齐
- 函数指针
- 指针例子
- main接收用户输入
- 内存布局
- 内存分区
- 空间开辟和释放
- 堆空间操作字符串
- 内存处理函数
- 内存分页
- 内存模型
- 栈
- 栈溢出攻击
- 内存泄露
- 大小端存储法
- 寄存器
- 结构体
- 共用体
- 枚举
- 文件操作
- 文件到底是什么
- 文件打开和关闭
- 文件的顺序读写
- 文件的随机读写
- 文件复制
- FILE和缓冲区
- 文件大小
- 插入,删除,更改文件内容
- typeid
- 内部链接和外部链接
- 动态库
- 调试器
- 调试的概念
- vs调试
- 多文件编程
- extern关键字
- 头文件规范
- 标准库以及标准头文件
- 头文件只包含一次
- static
- 多线程
- 简介
- 创建线程threads.h
- 创建线程pthread
- gdb
- 简介
- mac使用gdb
- setjump和longjump
- 零拷贝
- gc
- 调试器原理
- c++
- c++简介
- c++对c的扩展
- ::作用域运算符
- 名字控制
- cpp对c的增强
- const
- 变量定义数组
- 尽量以const替换#define
- 引用
- 内联函数
- 函数默认参数
- 函数占位参数
- 函数重载
- extern "C"
- 类和对象
- 类封装
- 构造和析构
- 深浅拷贝
- explicit关键字
- 动态对象创建
- 静态成员
- 对象模型
- this
- 友元
- 单例
- 继承
- 多态
- 运算符重载
- 赋值重载
- 指针运算符(*,->)重载
- 前置和后置++
- 左移<<运算符重载
- 函数调用符重载
- 总结
- bool重载
- 模板
- 简介
- 普通函数和模板函数调用
- 模板的局限性
- 类模板
- 复数的模板类
- 类模板作为参数
- 类模板继承
- 类模板类内和类外实现
- 类模板和友元函数
- 类模板实现数组
- 类型转换
- 异常
- 异常基本语法
- 异常的接口声明
- 异常的栈解旋
- 异常的多态
- 标准异常库
- 自定义异常
- io
- 流的概念和类库结构
- 标准io流
- 标准输入流
- 标准输出流
- 文件读写
- STL
- 简介
- string容器
- vector容器
- deque容器
- stack容器
- queue容器
- list容器
- set/multiset容器
- map/multimap容器
- pair对组
- 深浅拷贝问题
- 使用时机
- 常用算法
- 函数对象
- 谓词
- 内建函数对象
- 函数对象适配器
- 空间适配器
- 常用遍历算法
- 查找算法
- 排序算法
- 拷贝和替换算法
- 算术生成算法
- 集合算法
- gcc
- GDB
- makefile
- visualstudio
- VisualAssistX
- 各种插件
- utf8编码
- 制作安装项目
- 编译模式
- 内存对齐
- 快捷键
- 自动补全
- 查看c++类内存布局
- FFmpeg
- ffmpeg架构
- 命令的基本格式
- 分解与复用
- 处理原始数据
- 录屏和音
- 滤镜
- 水印
- 音视频的拼接与裁剪
- 视频图片转换
- 直播
- ffplay
- 常见问题
- 多媒体文件处理
- ffmpeg代码结构
- 日志系统
- 处理流数据
- linux
- 系统调用
- 常用IO函数
- 文件操作函数
- 文件描述符复制
- 目录相关操作
- 时间相关函数
- 进程
- valgrind
- 进程通信
- 信号
- 信号产生函数
- 信号集
- 信号捕捉
- SIGCHLD信号
- 不可重入函数和可重入函数
- 进程组
- 会话
- 守护进程
- 线程
- 线程属性
- 互斥锁
- 读写锁
- 条件变量
- 信号量
- 网络
- 分层模型
- 协议格式
- TCP协议
- socket
- socket概念
- 网络字节序
- ip地址转换函数
- sockaddr数据结构
- 网络套接字函数
- socket模型创建流程图
- socket函数
- bind函数
- listen函数
- accept函数
- connect函数
- C/S模型-TCP
- 出错处理封装函数
- 多进程并发服务器
- 多线程并发服务器
- 多路I/O复用服务器
- select
- poll
- epoll
- epoll事件
- epoll例子
- epoll反应堆思想
- udp
- socket IPC(本地套接字domain)
- 其他常用函数
- libevent
- libevent简介