华为技术有限公司C语言编程基础.ppt_第1页
华为技术有限公司C语言编程基础.ppt_第2页
华为技术有限公司C语言编程基础.ppt_第3页
华为技术有限公司C语言编程基础.ppt_第4页
华为技术有限公司C语言编程基础.ppt_第5页
已阅读5页,还剩81页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

华为技术有限公司C语言编程基础 内部公开 目录 前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If规范临界资源保护简单既是美 前言 提高我司产品竞争力 研发要在以下几个方面下功夫 提高规划水平 把握正确的方向 战略 提高设计水平 搭建合理的系统 战术 提高编码水平 开发稳定的代码 单兵作战技能 前言 我们为什么要进行培训 最好的医术是预防真正的难问题往往是低级错误引起的我们的编码水平不容乐观C是程序员的语言 前言 要提高编码水平 每个开发人员要做到 勤学苦练 提高编程技能前车之鉴 后世之师 不犯同样的错误 坚持代码Review PC LINT检查和单元测试 总而言之 就是少犯错误 尽早发现错误 目录 前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If规范临界资源保护简单既是美 基础篇之简单就是美 If aa的值是多少 基础篇之简单就是美 这里没有答案 只有问题 我们问什么要写这样的代码 工作太轻松 BUG不够多 水平显不出 如何改进 优先级搞不清楚用括号 复合语句太罗嗦 拆成几行来写 套用两句广告词 把简单的事情复杂化 太累把复杂的事情简单化 贡献 基础篇之简单就是美 编码的三不原则不要挑战自己的记性不要挑战同事的耐心不要挑战编译器的水平编码的三用原则能用简单语句的 就不要用复杂的技巧能用成熟代码的 就不要再来一套能用上工具的 就一定要机械化 我们要求什么 structXXX charcA shortsB longlC voidmain char pChar pChar char malloc 7 memcpy pChar abcdefgh sizeof XXX printf s n pChar return 我们要求什么 续 structXXX charcA shortsB longlC voidmain char pChar pChar char malloc 7 0 魔鬼数字 1 未申请成功怎么办 memcpy pChar abcdefgh sizeof XXX 2 内存越界 printf s n pChar 3 没有字符串结束符 return 4 没有释放内存 目录 前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If规范临界资源保护简单既是美 基础篇之sizeof 数据结构是C语言的基础C语言的灵活性很大程度上在于其数据结构的灵活性要用好数据结构 首先要掌握数据结构大小的计算系统为每个数据结构 每个变量都会分配一个对应的存储空间 这个存储空间的大小就是数据结构的尺寸 基础篇之sizeof typedefunionrecord LONGlIndex SHORTsLevel 6 CHARcPos REC S REC SstMax pMax CHARstr Hello CHAR pChar str ULONGulGrade 10 USHORTusClass 10 DOUBLEdWeightUCHAR pCharArray 10 10 Sizeof stMax pMax str pChar ulGrade usClass dWeight pCharArray 的取值分别是多少 基础篇之sizeof typedefunionrecord LONGlIndex SHORTsLevel 6 CHARcPos REC S REC SstMax 12 pMax 4 CHARstr Hello 5 1 6 不要忘了 0 CHAR pChar str 4 ULONGulGrade 10 4 USHORTusClass 10 2 DOUBLEdWeight 8 UCHAR pCharArray 10 10 4 10 10 400 目录 前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If规范临界资源保护简单既是美 基础篇之字节对齐 随着半导体技术的发展 我们经历8bit 16bit 32bit乃至64bit的CPU 我们产品当前大多使用32bitCPU从内存存取效率来说 4字节对齐的存取速度是最快的 非对齐情况下 CPU需要分解成两次32bit操作 缺省情况下 编译器自动对数据结构进行四字节对齐 以提高程序执行的效率 在特殊情况下 可以通过预编译指定指定数据结构为1字节对齐或者其他 对于PowerPC Intel系列CPU 在非四字节对齐情况下 由CPU自动完成两次操作 对上层应用透明 对于MIPSCPU 则需要通过编译选项进行干预 或者调整数据结果避免出现这种情况 否则会产生例外 字节对齐对数据结构的尺寸 sizeof 直接产生影响 基础篇之字节对齐 typedefstructHead CHARsrc 6 ULONGulType HEAD S VOIDEncapsulation CHAR pBuf ULONGulLen ulDestIP CHAR pData pBuf ulLen sizeof HEAD S pData ulLen ulDestIP VOS NTOHL IP S pData ulDestIP return 基础篇之字节对齐 pragmapack push pragmapack 1 typedefstructHead CHARsrc 6 ULONGulType HEAD S pragmapack pop VOIDEncapsulation CHAR pBuf ULONGulLen ulDestIP CHAR pData pBuf ulLen sizeof HEAD S pData len ulDestIP VOS NTOHL IP S pData ulDestIP MIPSCPU异常 return 基础篇之字节对齐 数据结构内部对齐 下面2种定义哪个好 typedefstructexample USHORTusA ULONGulA USHORTusB UCHARucA USHORTusC EXAMPLE SVStypedefstructexample ULONGulA USHORTusA USHORTusB USHORTusC UCHARucA UCHARucReserved EXAMPLE S 基础篇之字节对齐 案例点评在定义数据结构时 尤其是涉及协议和IPC通讯的时候 没有特殊理由的话 都定义成四字节对齐 这样做可能浪费几个字节 但是不会出问题 除了数据结构总长度是四字节对齐外 每一个部分也要保证它是四字节对齐的 可以按照四字节 两字节 一字节的顺序排放数据结构中的各个域 对于无法定义成四字节对齐的数据结构 如以太网II HDLC等 则将它们强行定义成一字节对齐 以规避这个问题 对于MIPSCPU 在必须面对非四字节对齐情况时 采用编译选项方式加以解决 目录 前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If规范临界资源保护简单既是美 基础篇之字节序 X86系统 VOIDQosConfigPolicy ulDestIP 从命令行读取用户配置的参数 pQosPolicy ulDestIP ulDestIP return 主机处理 VOIDQosClassify pIp IP S pData if pIp ulDestIp pQosPolicy ulDestIP DoSomething return 基础篇之字节序 X86系统 VOIDQosConfigPolicy ulDestIP 从命令行读取用户配置的参数 pQosPolicy ulDestIP ulDestIP return 主机处理 VOIDQosClassify pIp IP S pData if VOS HTONL pQosPolicy ulDestIP pIp ulDestIp DoSomething return 基础篇之字节序 由于历史的原因 业界存在两种字节序标准 BigEndian和LittleEndian PowerPC是大头 X86是小头 有些CPU可以通过寄存器设置支持不同的字节序 例如MIPS 所谓大头就是高位在低字节 低位在高字节 小头则与此相反 以0 x345678为例 大头内存从低到高的存放次序为00 34 56 78 小头内存从低到高的存放次序为78 56 34 00 上面的数值统一为16进制表示形式 字节序问题广泛存在于设备与设备之间 单板与单板之间 单板与底层芯片之间 只要两个处理单元的字节序不同 这个问题就存在 为了解决不同字节序的处理单元之间的通信问题 业界定义了主机序和网络序的概念 网络序主要用于信息传递 一般不用于计算 其字节顺序与大头一致 除了在编码时绷紧这根弦以外 我们在器件选择时尽量选择主机序与网络序一致的芯片 同一设备的不同单板使用相同的字节序 并优先选择支持大头的芯片 这样 即使不能彻底解决问题 也可以彻底规避问题 目录 前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If规范临界资源保护简单既是美 基础篇之函数参数 在C语言中 函数通过返回值和参数与调用者交换信息 对参数理解和使用的正确与否 直接影响到函数功能能否正确实现 函数参数自身占用的存储单元在堆栈中分配 入口参数指向的数值或者地址在函数入口处拷贝到堆栈区中 因此对函数参数所在存储单元的直接修改不会作用到函数之外 而对参数存储单元中存放的地址指向的存储空间的修改 则会在函数之外其作用 调用者在进行函数调用之前 必须事先申明被调用函数的原型 包括返回值类型和参数类型 基础篇之函数参数 BOOLGetMemory CHAR p 申请内存 p CHAR malloc 100 if NULL p returnFALSE else returnTRUE VOIDTest void CHAR str NULL If GetMemory str strcpy str helloworld printf str return 基础篇之函数参数 CHAR GetMemory CHAR p 申请内存 p CHAR malloc 100 return p VOIDTest void CHAR str NULL If NULL GetMemory 目录 前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If规范临界资源保护简单既是美 基础篇之返回值 在C语言中 函数的调用者通过返回值了解函数的执行情况 函数缺省的返回值类型为int 编程规范要求必须显示定义函数的返回类型 对于反映了函数执行状态的返回值 调用者必须依据返回值进行相应的处理 尤其是对于函数执行异常的情形 函数的出口参数能够起到与返回值类似的作用 上面一条规则对出口参数同样适用 对于函数返回值为恒值的函数 建议使用VOID类型的返回值 基础篇之返回值 有什么问题 include stdlib h VOIDmain CHAR p p CHAR malloc 100 VOS Strcpy p HelloWorld n printf p free p return 基础篇之返回值 include stdlib h VOIDmain CHAR p p CHAR malloc 100 if NULL p strcpy p HelloWorld n printf p free p return 基础篇之返回值 LONGA if 条件1 return returnVOS OK VOIDB if A DoSomeThing1 else DoSomeThing2 return 基础篇之返回值 LONGA if 条件1 returnVOS ERROR returnVOS OK VOIDB if A DoSomeThing1 else DoSomeThing2 return 目录 前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If规范临界资源保护简单既是美 基础篇之强制类型转换 强制类型转换给C语言编程带来了极大的灵活性 也正是这种灵活性 也埋下了无数的隐患 当目的结构的空间大于源结构的空间时 要重点关注内存访问超过源结构范围的情形 可能越界 当目的结构的空间小于源结构的空间时 要重点关注对目的结构赋值不能完全覆盖源结构范围的情形 可能遗漏 与结构体之间的强制类型转换相比 基本数据结构的强制类型转换更容易出现上面描述的情况 使用的时候 一定要慎之又慎 基础篇之类型转换 目的结构小于源结构 VOIDB CHAR p p 1 return VOIDA ULONGa B CHAR a 是1吗 基础篇之类型转换 目的结构小于源结构 VOIDB CHAR p p 1 return VOIDA ULONGa B CHAR a 是1吗 不可预知 基础篇之类型转换 目的结构大于源结构 VOIDB ULONG p p 1000 return VOIDA UCHARa 10 B ULONG 在函数B给 p赋值之前 p的值是多少 p赋值之后 会出现什么样的情形 基础篇之类型转换 目的结构大于源结构 VOIDB ULONG p p 1000 return VOIDA UCHARa 10 B ULONG 在函数B给 p赋值之前 p的值是多少 不可预知 p赋值之后 会出现什么样的情形 越界 目录 前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If规范临界资源保护简单既是美 基础篇之switch case C语言使用switch case处理一个条件的多个取值有不同的处理分支的情形 当所有的case都匹配不成功时 进入default分支 编程规范要求switch case必须显示设置default分支 如果程序从逻辑上不可能走到这个分支 可以在该分支中使用断言 结束case分支的执行最常用的办法是使用break return 否则程序将自动进入下一个case分支继续执行 编译器对switch case可以做优化 用空间换取时间 default分支按照编程规范 要求放在switchcase的末尾 C语言本身不做强制要求 基础篇之switch case VOIDmain LONGulCnt1 0 ulCnt2 0 CHAR ch aha while ch switch ch case a case h ulCnt2 default ulCnt1 ch printf u u n ulCnt1 ulCnt2 return ulCnt1和ulCnt2分别是多少 基础篇之switch case VOIDmain LONGulCnt1 0 ulCnt2 0 CHAR ch aha while ch switch ch case a case h ulCnt2 default ulCnt1 ch printf u u n ulCnt1 ulCnt2 return ulCnt1 4ulCnt2 3 目录 前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If规范临界资源保护简单既是美 基础篇之字符串 ULONGBuildRun CHAR ppBuildrun ULONGulLen CHAR pBuf ulLen CalculateBuildRunLen if 0 ulLen ppBuildrun NULL returnB ZERO LENGTH pBuf VOS malloc 0 ulLen if NULL pBuf ppBuildrun NULL returnB MALLOC FAILED VOS StrCpy pBuf BuildRunInfo ppBuildrun pBuf returnVOS OK 基础篇之字符串 ULONGBuildRun CHAR ppBuildrun ULONGulLen CHAR pBuf ulLen CalculateBuildRunLen if 0 ulLen ppBuildrun NULL returnB ZERO LENGTH pBuf VOS malloc 0 ulLen 1 if NULL pBuf ppBuildrun NULL returnB MALLOC FAILED VOS StrCpy pBuf BuildRunInfo ppBuildrun pBuf returnVOS OK 基础篇之字符串 案例点评 作为信息输出 字符串必不可少 字符串在动态申请时少分配一个字符是非常普遍的一个错误 strlen等计算字符串长度的函数都是不考虑字符串的 0结束符的 代码Review时 字符串越界问题是一个大客户 要盯紧看严 基础篇之字符串 续 再看一个例子 LONGGetXYZHead CHAR pData CHAR pBuf ULONGulLen CHAR pTmpData pData pTmpBuf pBuf ulLen AnalysisHead pTmpBuf strcpy pTmpData pTmpBuf sprintf pTmpData s pTmpBuf memcpy pTmpData pTmpBuf ulLen returnulLen pBuf中存放是是XYZ协议的Peer发送过来的一段报文 这个函数负责将协议头拷贝到pData指向的空间中 假设空间是足够的 打算选择哪条语句 基础篇之字符串 续 LONGGetXYZHead CHAR pData CHAR pBuf ULONGulLen CHAR pTmpData pData pTmpBuf pBuf ulLen AnalysisHead pTmpBuf strcpy pTmpData pTmpBuf sprintf pTmpData s pTmpBuf memcpy pTmpData pTmpBuf ulLen returnulLen 使用memcpy 因为没有人保证协议头中不出现 0 而且协议头非常容易出现这个值 这个时候它就不再是字符串 字符串工具函数必须是专款专用 而memcpy则要宽泛得多 基础篇之字符串 再续 VOIDGetDigitString CHAR pData CHAR pBuf CHAR pTmpData pData pTmpBuf pBuf while 0 pTmpBuf if 0 pTmpBuf pTmpData pTmpBuf pTmpData else break pTmpBuf return 该函数的功能是将pBuf中的连续数字拷贝到pData中生成一个新的字符串 基础篇之字符串 再续 VOIDGetDigitString CHAR pData CHAR pBuf CHAR pTmpData pData pTmpBuf pBuf while 0 pTmpBuf if 0 pTmpBuf pTmpData pTmpBuf pTmpData else break pTmpBuf pTmpData 0 没有尾字符 就不是字符串 return 目录 前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If规范临界资源保护简单既是美 基础篇之溢出 defineDEFAULT EXPIRE TIME300000 5分钟 VOIDARPRecordExpireTime ARP Entry S pArpEntry 计算表项预计老化时的时间 以系统启动以来的毫秒数表示 pARPEntry ulExpireTime GetBootTime DEFAULT EXPIRE TIME return VOID ARPExpire ARP Entry S pArpEntry ARP Entry s pArpNext while pArpEntry if GetBootTime ulExpireTime break pArpNext pArpEntry pNext Free pArpEntry pArpEntry pArpNext return VOID pArpEntry 基础篇之溢出 defineDEFAULT EXPIRE TIME300000 5分钟 VOIDARPRecordExpireTime ARP Entry S pArpEntry 计算表项预计老化时的时间 以系统启动以来的毫秒数表示 pARPEntry ulExpireTime GetBootTime DEFAULT EXPIRE TIME return VOID ARPExpire ARP Entry S pArpEntry ARP Entry s pArpNext while pArpEntry if GetBootTime ulExpireTime ULONG溢出如何处理 包括ExpireTime溢出 GetBootTime溢出 解决方案作为思考题 break pArpNext pArpEntry pNext Free pArpEntry pArpEntry pArpNext return VOID pArpEntry 基础篇之溢出 案例点评 在我们的系统中 溢出通常出现在时间处理上 系统时钟一般使用两个ULONG表示时间 精确到毫秒 上层软件使用时间时一般忽略掉高位 只保留低32位 对于LONG的情况 25天后翻转 对于ULONG的情况 49天后翻转 如果没有特殊的需要 建议使用系统提供的精确到秒的32位时钟 在LONG情况下60年翻转 基本可以不考虑这件事情 如果一定要使用毫秒钟 就需要考虑时钟翻转的情况 基础篇之溢出 续 ULONGSequenceAdd ULONGulCount ULONGulSum 0 while 0 ulCount ulSum ulCount ulCount returnulSum 基础篇之溢出 续 ULONGSequenceAdd ULONGulCount ULONGulSum 0 while 0 ulCount 条件永远为真 死循环 ulSum ulCount ulCount returnulSum 基础篇之溢出 续二 VOIDShowLong ULONGulCount CHARstInfo 16 VOS Sprintf stInfo ld n r ulCount Printf stInfo return 基础篇之溢出 续二 VOIDShowLong ULONGulCount CHARstInfo 16 VOS Sprintf stInfo lu n r ulCount Printf stInfo return 在显示无符号整数时 使用正确的 描述符 基础篇之溢出 续 案例点评 要解决溢出问题 首先要明确数据结构的取值范围 无符号数和有符号数在取值范围上的差异 也容易引起溢出 若非特殊需要 不要进行有符号数和无符号数的强制类型转换 以免产生不必要的麻烦 若非特殊需要 不要进行从 U LONG到 U SHORT到 U char的转换 以免产生不必要的麻烦 目录 前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If规范临界资源保护简单既是美 基础篇之资源释放 VOIDPrintDigit ULONGulData CHAR pBuf pBuf CHAR malloc 16 if NULL pBuf returnNULL VOS Sprintf pBuf lu n r ulData printf pBuf return 基础篇之资源释放 VOIDPrintDigit ULONGulData CHAR pBuf pBuf CHAR malloc 16 if NULL pBuf returnNULL VOS Sprintf pBuf lu n r ulData printf pBuf Free pBuf Review九句箴言 看见Malloc找Free return 基础篇之资源释放 续 Node Head S CreateNode ULONGulNType Node Head S pNode Node Body S pBody pNode Node Head S malloc sizeof Node Head S if NULL pNode returnNULL pBody Node Body S malloc sizeof Node Body S if NULL pBody returnNULL pNode pBody pBody pNode ulNType ulNType returnpNode 基础篇之资源释放 续 Node Head S CreateNode ULONGulNType Node Head S pNode Node Body S pBody pNode Node Head S malloc sizeof Node Head S if NULL pNode returnNULL pBody Node Body S malloc sizeof Node Body S if NULL pBody Free pNode 异常分支最容易忘记打扫战场 顾头也要顾尾 returnNULL pNode pBody pBody pNode ulNType ulNType returnpNode 基础篇之资源释放 案例点评资源泄漏是代码Review中最常见的错误之一申请的每个资源必须明确由谁负责释放 何时释放 在何处释放 在异常分支中 保持清醒的头脑 清理战场 在特定功能去使能时 需要完成的主要工作就是资源清退 目录 前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If规范临界资源保护简单既是美 基础篇之if规范 LONGIsZero ULONGulCnt if ulCnt 0 returnW ZERO else returnW NONZERO 函数的功能为 参数为0时返回W ZERO 否则返回W NOZERO 基础篇之if规范 LONGIsZero ULONGulCnt if 0 ulCnt returnW ZERO else returnW NONZERO 编程规范反复强调变量放在双等号的右边 常量放在左边 就是为了规避出现If ulCnt 0 这种语法正确 但是极有可能是笔误的情况 为了杜绝这种不必要的逻辑问题 要求必须严格遵守编程规范 基础篇之if规范 续 If ulCnt ulData VsulCnt ulData If ulCnt VsIf ulCnt ulData 上面的语句语法上都是正确的 但写法哪个好 基础篇之if规范 续 If ulCnt ulData VsulCnt ulData If ulCnt VsIf ulCnt ulData 第一种和第三种非常容易出现笔误 为了杜绝不必要的问题 不要使用第一种方式编写程序 而用方式二替代 基础篇之if规范 再续 VOIDTest if Func A 在任何情况下是否语义都是正确的 基础篇之if规范 再续 VOIDTest VOIDTest ULONGulRet1 ulRet2 if Func A ulRet1 Func A ulRet2 Func B if Func B if ulRet1 如果程序逻辑为Func A的返回值为假的情况下 不执行Func B 则上一页的程序是正确的 但是要求采用本页右侧的程序模式实现 如果Func A和Func B都无条件执行 再根据综合结果 决定走哪个分支 则使用本页左侧的程序 为了明确程序逻辑 同时要求使用注释加以说明 以方便后期的维护 基础篇之if规范 续三 VOS Assert Func A vsVOS DBGASSERT Func A 这两个用法有什么区别 VOS Aseert 用法保证在任何情况下Func A都得到执行 VOS DBGASSERT则与系统是打开release宏还是debug宏相关 当系统打开了debug宏时 起语义与方式1完全相同 当系统打开的是release宏 则VOS DBGASSERT在编译时将被忽略 Func A自然页得不到运行 使用VOS DBGASSERT的时候要谨慎 要清楚了解不同系统宏下的不同语义 要保证两种场景下 程序逻辑都是正确的 为了避免不必要的麻烦 要求不允许在VOS DBGASSERT中使用函数 基础篇之if规范 续四 LONGIsA CHARch if a ch A ch returnVOS ERROR else returnVOS OK 函数功能为判断输入的字符是否是 a 或者 A 如果是 则返回VOS OK 否则返回VOS ERROR 基础篇之if规范 续四 LONGIsA CHARch if a ch A ch 逻辑恒为真 逻辑错误 笔误 returnVOS ERROR else returnVOS OK PC LINT可以检查出逻辑恒为真或者假的逻辑表达式 基本都是我们预期之外的逻辑 PC LINT确实是一个好东西 目录 前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If规范临界资源保护简单既是美 基础篇之临界资源保护 VOIDSendMBuf MBUF S pMBuf 空闲BD数 DRV GetFreeBD 报文片数 MBUF GetFrag pMBuf if 报文片数 空闲BD数 return 发送拥塞 暂时缓存 intr lock CopyMBufIntoBD 空闲BD数 报文片数 intr unlock TaskSOCK Intr SendMBuf pMBuf SendMBuf pMBuf 基础篇之临界资源保护 VOIDSendMBuf MBUF S pMBuf intr lock 彻底保护

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论