如何新建自己的网站自己做网站卖东西需要交税吗
2026/1/10 11:27:34 网站建设 项目流程
如何新建自己的网站,自己做网站卖东西需要交税吗,常见营销策略都有哪些,南昌莱布网络科技有限公司一、结构体核心概念#xff08;C/C 通用#xff09; 结构体#xff08;struct#xff09;是用户自定义的复合数据类型#xff0c;核心作用是将不同类型的基础数据#xff08;如int、char、指针等#xff09;封装为一个整体#xff0c;用来描述现实中 “具有多个属性的…一、结构体核心概念C/C 通用结构体struct是用户自定义的复合数据类型核心作用是将不同类型的基础数据如int、char、指针等封装为一个整体用来描述现实中 “具有多个属性的复杂对象”比如 “学生” 包含学号、姓名、成绩“汽车” 包含品牌、价格、排量。对比维度C 语言结构体C 结构体类型名使用必须加struct关键字除非用typedef取别名结构体名本身就是合法类型名可直接使用无需struct成员权限无访问控制所有成员默认公开且无public/private/protected关键字支持访问控制默认public可显式指定private/protected成员类型仅支持数据成员变量不能定义函数支持数据成员 成员函数包括构造 / 析构函数、重载运算符、静态函数等继承特性无继承概念无法继承其他结构体 / 类型可继承其他结构体 / 类默认 public 继承支持多态模板支持无模板机制无法泛型化可结合模板template实现泛型结构体与类的关系无 “类” 的概念结构体仅用于封装数据和class几乎等价仅默认权限 / 继承方式不同可实现类的所有功能初始化方式仅支持聚合初始化C99 起支持指定成员初始化无构造函数支持列表初始化、构造函数初始化、赋值初始化等更灵活二、结构体的定义与声明语法结构体的定义需用struct关键字常见有 3 种方式同时可通过typedef定义别名简化 C 中使用。2.1 基础定义方式方式 1先定义类型再声明变量最常用// 定义结构体类型struct StudentC中使用时需加structC可省略 struct Student { int id; // 成员1学号int类型 char name[20]; // 成员2姓名字符数组 float score; // 成员3成绩float类型 }; // 声明变量stu1、stu2是struct Student类型的对象 struct Student stu1, stu2;方式 2定义类型的同时声明变量// 定义struct Teacher类型并直接声明tea1、tea2两个变量 struct Teacher { int id; char subject[30]; } tea1, tea2;方式 3匿名结构体无类型名仅能在定义时声明变量匿名结构体没有类型名无法复用后续不能再声明同类型变量仅适用于临时、单一对象// 匿名结构体仅能使用rect这一个变量 struct { double width; double height; } rect;2.2typedef定义结构体别名C 中常用C 语言中每次使用结构体都要写struct 类型名可通过typedef定义别名简化书写// 方式1分开写 struct Student { int id; char name[20]; }; typedef struct Student Stu; // 别名Stu等价于struct Student // 方式2合并写更常用 typedef struct Student { int id; char name[20]; } Stu; // 声明变量直接用别名Stu Stu stu1;2.3 C 中 using 定义结构体别名的写法using是 C11 及以后推荐的别名声明方式语法比typedef更直观尤其是处理复杂类型时优势更明显。针对结构体主要有两种常用写法写法 1先定义结构体再用 using 取别名// 第一步定义结构体C 中结构体名本身就是合法类型名无需像C那样依赖struct struct Student { int id; // 学号 char name[20]; // 姓名 }; // 第二步用 using 定义别名 Stu等价于 struct StudentC 中struct可省略 using Stu Student; // 推荐写法最简洁 // 也可以写using Stu struct Student; 兼容C的写法不推荐写法 2匿名结构体 using 更紧凑适合一次性定义如果不需要保留原结构体名可直接定义匿名结构体并取别名// 直接定义匿名结构体并为其取别名 Stu using Stu struct { int id; char name[20]; };using 对比 typedef 的优势以函数指针这类复杂类型为例能更明显看出using的可读性优势// typedef 定义函数指针别名写法绕新手易混淆 typedef void (*FuncPtr)(int); // using 定义函数指针别名语法直观“别名 类型”的逻辑更清晰 using FuncPtr void (*)(int);三、结构体成员的访问访问结构体成员需根据变量类型普通变量 / 指针变量选择不同的操作符3.1 普通变量用.成员访问操作符#include stdio.h #include string.h typedef struct Student { int id; char name[20]; } Stu; int main() { Stu stu; stu.id 1001; // 普通变量用.访问成员 strcpy(stu.name, 张三);// 字符串需用strcpy赋值 printf(学号%d姓名%s\n, stu.id, stu.name); return 0; }3.2 指针变量用-指针成员访问操作符若结构体变量是指针需用-访问成员等价于(*指针).成员int main() { Stu stu; Stu *p stu; // 结构体指针指向stu的地址 p-id 1002; // 指针用-访问成员 strcpy(p-name, 李四);// 等价于 (*p).name 李四 printf(学号%d姓名%s\n, p-id, p-name); return 0; }四、结构体的初始化结构体的初始化方式因 C/C 标准不同而有所差异4.1 C 语言初始化1C89 标准按成员顺序初始化必须严格按照结构体成员的定义顺序赋值未赋值的成员默认初始化为0Stu stu1 {1001, 张三}; // 按顺序id→namescore默认0.02C99 标准指定成员名初始化推荐可通过.[成员名]指定成员赋值顺序任意未赋值成员默认0Stu stu2 { .name 王五, .id 1003 }; // id1003name王五score0.0注意!!!:这个C99标准的写法是罕见的C兼容的C语言的语法, 这种写法在大多数C编译器中会报错!!!3外部赋值初始化先定义再赋值,缺点是容易漏掉变量,忘记赋值Stu stu3; stu3.id1003 stu3.name王五 stu3.score0.04.2 C 初始化C 兼容 C 的初始化方式同时支持更灵活的写法1列表初始化C11struct Student { int id; char name[20]; float score; }; Student stu {1001, 张三, 95.5}; // 顺序列表初始化 Student stu2 {.name 李四, .id 1002}; // 指定成员初始化C112构造函数初始化C 特有C 结构体可定义构造函数在创建对象时自动初始化后续第 10 节详细讲。五、结构体的内存布局与内存对齐核心重点结构体的大小不是成员大小的简单相加而是遵循内存对齐规则编译器为提升 CPU 访问效率的优化策略。5.1 内存对齐规则通用第一个成员偏移量相对于结构体起始地址的距离为0每个成员偏移量必须是「该成员自身对齐值大小」的整数倍结构体总大小必须是「结构体中最大基本类型成员对齐值大小」的整数倍。5.2 示例计算结构体大小#include stdio.h // 定义结构体 struct Test { char a; // 大小1字节偏移0符合规则 int b; // 大小4字节偏移需是4的整数倍 → 偏移4a后补3字节“内存空洞” short c; // 大小2字节偏移844是2的整数倍 → 符合规则 }; int main() { printf(结构体大小%zu\n, sizeof(struct Test)); // 输出8134210不总大小需是最大成员int4的整数倍 → 补2字节总大小12 // 注意不同编译器可能有不同对齐策略可通过#pragma pack(n)修改对齐系数 return 0; }5.3 为什么要内存对齐CPU 访问内存时会按 “字长”如 32 位 CPU 字长 4 字节批量读取。若数据未对齐CPU 需分 2 次读取并拼接效率低对齐后可 1 次读取牺牲少量内存换效率。5.4 关于结构体大小的详细计算https://mp.csdn.net/mp_blog/creation/editor/155817717六、结构体嵌套结构体可以包含另一个结构体作为成员嵌套用来描述更复杂的对象// 定义“地址”结构体 struct Address { char city[20]; char street[50]; }; // 定义“学生”结构体嵌套Address struct Student { int id; char name[20]; struct Address addr; // 嵌套结构体成员 }; int main() { // 初始化嵌套结构体 struct Student stu { .id 1001, .name 张三, .addr {.city 北京, .street 中关村大街} }; // 访问嵌套成员逐层用. printf(城市%s街道%s\n, stu.addr.city, stu.addr.street); return 0; }七、结构体与函数结构体可以作为函数的参数、返回值核心有 2 种传递方式7.1 值传递拷贝传递将结构体的完整副本传给函数函数内修改的是 “副本”不影响原结构体缺点结构体较大时拷贝开销高// 值传递修改的是副本 void modify_stu(Stu s) { s.id 2000; } int main() { Stu stu {1001, 张三}; modify_stu(stu); printf(学号%d\n, stu.id); // 输出1001原数据未变 return 0; }7.2 指针传递推荐传递结构体的地址函数内直接操作原数据无拷贝开销// 指针传递修改原数据 void modify_stu_ptr(Stu *s) { s-id 2000; } int main() { Stu stu {1001, 张三}; modify_stu_ptr(stu); printf(学号%d\n, stu.id); // 输出2000原数据被修改 return 0; }7.3 结构体作为返回值函数可以返回结构体本质是值传递返回副本Stu create_stu(int id, const char *name) { Stu s; s.id id; strcpy(s.name, name); return s; } int main() { Stu stu create_stu(1004, 赵六); printf(学号%d姓名%s\n, stu.id, stu.name); return 0; }八、结构体中的数组与指针结构体中可以包含数组或指针但内存管理方式完全不同8.1 结构体中的数组数组内存直接存储在结构体中大小固定struct Student { char name[20]; // 数组内存属于结构体大小固定为20字节 };8.2 结构体中的指针指针仅存储地址指向的内存不在结构体中需手动分配 / 释放易引发内存泄漏struct Student { char *name; // 指针仅存地址需手动分配内存 }; int main() { struct Student stu; // 手动分配内存 stu.name (char*)malloc(20); strcpy(stu.name, 张三); printf(姓名%s\n, stu.name); // 手动释放内存避免泄漏 free(stu.name); return 0; }8.3 浅拷贝问题结构体含指针时若直接赋值含指针的结构体会发生浅拷贝仅拷贝指针地址不拷贝指针指向的内容导致多个结构体指针指向同一块内存释放时重复释放int main() { struct Student stu1, stu2; stu1.name (char*)malloc(20); strcpy(stu1.name, 张三); stu2 stu1; // 浅拷贝仅拷贝指针地址stu2.name和stu1.name指向同一块内存 free(stu1.name); // 释放stu1.name free(stu2.name); // 重复释放触发内存错误 return 0; }解决方法深拷贝手动拷贝指针指向的内容而非仅拷贝地址void copy_stu(struct Student *dest, struct Student *src) { dest-id src-id; // 深拷贝分配新内存拷贝内容 dest-name (char*)malloc(strlen(src-name) 1); strcpy(dest-name, src-name); }九、结构体的进阶特性9.1 柔性数组C99 特有结构体的最后一个成员可以是 “未指定大小的数组”柔性数组用于动态分配内存数组大小由malloc指定// 柔性数组最后一个成员是未指定大小的数组 struct Buffer { int len; char data[]; // 柔性数组大小为0C99支持 }; int main() { // 分配内存Buffer大小 100字节的data数组 struct Buffer *buf (struct Buffer*)malloc(sizeof(struct Buffer) 100); buf-len 100; strcpy(buf-data, 这是柔性数组的内容); printf(内容%s\n, buf-data); free(buf); // 一次释放即可 return 0; }C标准不支持柔性数组, 虽然大多数编译器做了拓展支持, 但是C 中优先使用std::vector/std::string/ 智能指针替代柔性数组, 避免手动内存管理的错误, 符合 C 的 RAII 理念在定义 Buffer 结构体时为什么选择char data[]这种柔性数组写法而非更直观的char* data?9.2 柔性数组 vs char* data 的本质区别用char* data虽然语法上可行但会带来内存不连续、管理复杂、易出错等问题而柔性数组的核心优势是内存连续、管理简单、性能更优这也是 C99 引入柔性数组的根本原因。1. 内存布局连续 vs 分散这是最核心的区别直接决定了后续的所有差异柔性数组char data []data是结构体的 “一部分”和len在同一块连续内存中。malloc 时只需一次分配sizeof(struct Buffer) 数据长度内存布局如下内存地址低 → 高 | len (4字节) | data[0] | data[1] | ... | data[99] | 连续的一块内存示例中malloc(sizeof(struct Buffer) 100)分配的是 “4 字节 len 100 字节 data” 的连续内存。char* date指针data只是结构体里的一个指针变量4/8 字节它指向另一块独立的内存。需要两次 malloc第一步分配结构体内存 → 存储 len 和 data指针 | len (4字节) | data指针 (8字节) | 第二步分配数据内存 → data指针指向这块内存 ↓ | 数据内容 | 另一块独立内存2. 内存管理简单 vs 复杂易出错这是实际开发中最容易踩坑的点1柔性数组的管理简单安全// 你的原代码一次分配一次释放 struct Buffer *buf (struct Buffer*)malloc(sizeof(struct Buffer) 100); buf-len 100; strcpy(buf-data, 这是柔性数组的内容); free(buf); // 一次free即可释放所有内存无内存泄漏2char* data 的管理复杂易出错struct Buffer { int len; char* data; // 指针版本 }; int main() { // 第一步分配结构体内存 struct Buffer *buf (struct Buffer*)malloc(sizeof(struct Buffer)); if (buf NULL) return -1; // 第二步分配数据内存必须单独分配 buf-len 100; buf-data (char*)malloc(buf-len); if (buf-data NULL) { // 需额外判空否则内存泄漏 free(buf); return -1; } strcpy(buf-data, 这是指针版本的内容); printf(内容%s\n, buf-data); // 释放必须先释放data指向的内存再释放结构体 // 顺序错了先free(buf) → data指针变成野指针无法释放data内存内存泄漏 // 漏释放data直接free(buf) → data指向的内存永远无法释放内存泄漏 free(buf-data); free(buf); return 0; }必须两次 malloc、两次 free步骤繁琐释放顺序不能错先 data 后结构体新手极易写错任何一步 malloc 失败都要手动回滚释放已分配的内存否则泄漏。3. 性能与缓存友好性更优 vs 较差CPU 访问内存时会优先读取 “缓存行”连续的内存块连续内存的访问效率远高于分散内存柔性数组len和data在同一块连续内存CPU 一次缓存就能加载访问buf-len后再访问buf-data时数据已在缓存中速度快char* data结构体和数据内存分散CPU 需要两次缓存加载先加载结构体再加载数据缓存命中率低性能稍差高频访问时差异明显。4. 内存碎片更少 vs 更多频繁分配 / 释放内存时柔性数组的优势更明显柔性数组一次分配大块连续内存减少内存碎片char* data两次小内存分配容易产生大量零散的内存碎片导致后续 malloc 失败即使总空闲内存足够也没有连续的大块内存。5. 边界与安全性更可控 vs 易出错柔性数组通过sizeof(struct Buffer) n分配能精准控制数据区大小且data是结构体的一部分不会出现 “结构体有效但 data 指针悬空” 的情况char* data需要手动记录len和data指向的内存大小容易出现 “len 和实际内存大小不一致”比如 len 设为 100但 data 只分配了 50 字节导致越界访问。9.3 匿名结构体嵌套场景嵌套结构体时可省略类型名匿名简化代码struct Student { int id; // 匿名嵌套结构体 struct { char city[20]; char street[50]; } addr; }; int main() { struct Student stu {.id1001, .addr.city上海}; printf(城市%s\n, stu.addr.city); return 0; }十、C 中结构体的扩展C 特有C 中的struct本质上与class几乎一致仅默认访问权限不同struct默认publicclass默认private支持面向对象特性10.1 结构体可以包含成员函数C 的结构体仅能存数据C 的结构体可以同时存 “数据成员变量” 和 “行为成员函数”#include iostream using namespace std; struct Student { // 成员变量默认public int id; string name; // C可直接用string // 成员函数打印信息 void print() { cout 学号 id 姓名 name endl; } }; int main() { Student stu {1001, 张三}; stu.print(); // 调用成员函数 return 0; }10.2 构造 / 析构函数C 特有构造函数创建对象时自动调用用于初始化析构函数销毁对象时自动调用用于释放资源。struct Student { int id; string name; // 构造函数与结构体同名无返回值 Student(int id_, string name_) { id id_; name name_; } // 析构函数~开头无参数 ~Student() { cout 销毁对象 name endl; } }; int main() { Student stu(1002, 李四); // 调用构造函数 stu.print(); return 0; // 函数结束析构函数自动调用 }10.3 继承与多态C 特有C 结构体支持继承和虚函数实现多态// 基类结构体 struct Shape { virtual double get_area() { return 0; } // 虚函数 virtual ~Shape() {} // 虚析构函数确保子类析构被调用 }; // 子类结构体继承Shape struct Circle : public Shape { double radius; Circle(double r) : radius(r) {} // 重写虚函数 double get_area() override { return 3.14 * radius * radius; } }; int main() { Shape *s new Circle(5); cout 圆形面积 s-get_area() endl; // 多态调用 delete s; return 0; }10.4 运算符重载C 特有C 结构体可以重载运算符让结构体支持更直观的操作struct Point { int x, y; // 重载运算符 Point operator(const Point p) { return {x p.x, y p.y}; } }; // 重载运算符输出 ostream operator(ostream os, const Point p) { os ( p.x , p.y ); return os; } int main() { Point p1 {1,2}, p2 {3,4}; Point p3 p1 p2; cout p3 endl; // 输出(4,6) return 0; }十一、结构体与联合体union的区别特性结构体struct联合体union内存分配各成员占独立内存所有成员共享同一块内存大小成员大小之和含内存空洞最大成员的大小用途封装不同类型数据节省内存同一时间存一种数据十二、C结构体和C类的区别唯一的区别就是没有区别对比维度struct结构体class类默认成员访问权限未显式指定时成员默认public公开未显式指定时成员默认private私有默认继承方式未显式指定时默认public继承未显式指定时默认private继承语法兼容性兼容 C 语言结构体写法可直接定义 C 风格结构体纯 C 特性无 C 语言兼容版本设计意图 / 编程规范偏向「数据聚合」封装简单、无复杂行为的纯数据集合如坐标、配置参数偏向「对象」封装完整的「数据 行为」强调接口与实现分离如学生、汽车等业务对象POD 类型兼容性更容易满足 POD 类型Plain Old Data可直接和 C 语言内存布局兼容若有private/ 虚函数等会失去 POD 特性模板特化写法template struct Aint {};template class Aint {};

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询