自己免费做网站(二)怎么做盗版小说网站

张小明 2025/12/31 18:52:43
自己免费做网站(二),怎么做盗版小说网站,网站后台上传图片无法显示,东莞网站建设网络公司排名快速的C语言复习PartA 完整的仓库地址在Tutorial_AwesomeModernCPP中#xff0c;您也可以光顾一下#xff0c;喜欢的话给一个Star激励一下作者 尽管#xff0c;笔者要说明的是C在今天已经不可以使用简单的C超集来描述C了#xff0c;但是因为设计之初#xff0c;C就是要求尽…快速的C语言复习PartA完整的仓库地址在Tutorial_AwesomeModernCPP中您也可以光顾一下喜欢的话给一个Star激励一下作者尽管笔者要说明的是C在今天已经不可以使用简单的C超集来描述C了但是因为设计之初C就是要求尽力兼容C语言的。所以这里我们默认大家的C语言水平都是可以合格的写出一个可以运行的基于某款或者是若干嵌入式联合系统的业务体系代码的。因此这里只是快速的出于完整的补充下C语言中常识的部分。1. 基本数据类型与类型修饰符值得一说的是C语言本身就是一个强类型的程序设计语言。澄清一个变量是什么是从C诞生以来就必须要做的标准动作。我知道有人会说auto的事情auto的确非常适合节约时间书写复杂的类型但是笔者的态度是不要滥用。C语言的类型系统是整个语言的基础在嵌入式开发中准确理解数据类型的大小和表示范围尤为重要因为硬件资源往往是受限的。在我们编写C的时候也是要注意这个事情。1.1 整型家族C语言提供了丰富的整型类型每种类型都有其特定的用途和表示范围。需要注意的是除了char类型在某些平台上固定为8位外其他整型的实际大小是由具体实现决定的。charcA;// 至少8位通常用于字符shorts100;// 至少16位inti1000;// 至少16位通常为32位longl100000L;// 至少32位longlongll100000LL;// 至少64位C99标准引入在嵌入式系统中我们经常需要精确控制数据类型的大小。C99标准引入的stdint.h头文件提供了固定宽度的整型这在编写可移植的嵌入式代码时极为重要特别是一些基础库你的东西可能会在32位到64位都会被使用笔者注意到现在已经开始慢慢出现用于嵌入式平台的64位芯片了所以还真要关心下#includestdint.hint8_ti8-128;// 精确8位有符号整数uint8_tu8255;// 精确8位无符号整数int16_ti16-32768;// 精确16位有符号整数uint16_tu1665535;// 精确16位无符号整数int32_ti32-2147483648;// 精确32位有符号整数uint32_tu324294967295U;// 精确32位无符号整数那问题来了什么时候用多大的呢嗯这个事情可以不必要如此的死板不过有一个事情必须注意——你的数据范围得够用。那问题来了**N 位的数据到底能存多大**对于无符号整数N 位一共可以表示2ⁿ 个数取值范围是0 ~ 2ⁿ − 1。那如果是有符号整数呢最高位要拿来当符号位了采用补码表示的话范围就是−2ⁿ⁻¹ ~ 2ⁿ⁻¹ − 1。大家都是嵌入式程序员这点二进制应该都能算得过来。1.2 浮点类型浮点类型用于表示实数但在嵌入式系统中使用浮点运算需要格外谨慎因为许多微控制器不支持硬件浮点运算软件模拟会带来显著的性能开销。floatf3.14f;// 单精度通常32位精度约7位十进制数doubled3.14159265359;// 双精度通常64位精度约15位十进制数longdoubleld3.14L;// 扩展精度至少与double相同在一些资源极端受限的嵌入式系统中如果必须使用浮点运算优先选择float而非double因为它占用更少的内存和运算资源double有时候太吃操作了。1.3 类型修饰符类型修饰符可以改变基本类型的属性在嵌入式编程中有着特殊的重要性。signed 和 unsignedunsigned修饰符将整型变量的表示范围扩展到仅非负数这在处理硬件寄存器值和位掩码时非常有用unsignedintcounter0;// 范围0 到 429496729532位系统signedinttemperature-40;// 范围-2147483648 到 2147483647const 修饰符const关键字声明变量为只读这在嵌入式开发中有多重作用。首先它可以帮助编译器进行优化将常量数据放置在ROM或Flash中而非RAM中节省宝贵的RAM资源。其次它提供了编译时的安全检查防止意外修改不应改变的数据这有时候很重要实际上就是强调当前逻辑下这个是不变量当然C还提供更为牛逼的constexpr这个等到C的时候我们继续聊constintMAX_BUFFER_SIZE256;// 常量整数constuint8_tlookup_table[]{0,1,4,9,16,25};// 常量数组可存放在Flash中在函数参数中使用const可以明确表明函数不会修改传入的数据这在设计API时是良好的实践voidprocess_data(constuint8_t*data,size_tlength){// 函数承诺不修改data指向的内容}volatile 修饰符volatile的字面含义是“易变的”它是嵌入式 C 编程中极其重要、但也最容易被误解的一个关键字。它的核心作用并不是“禁止编译器优化”而是明确地告诉编译器这个变量的值可能会在当前程序控制流之外发生变化。在嵌入式系统中这种“控制流之外”的变化通常来自硬件外设、中断服务程序ISR、DMA或其他并发执行上下文。正因为如此编译器在面对被volatile修饰的对象时不能假设该变量在两次访问之间保持不变。对于volatile变量的每一次读和写在抽象机模型中都属于可观察行为必须真实地发生在内存中而不能被缓存到寄存器、合并或直接消除。这并不意味着编译器“完全不能优化”而是它不能对volatile对象做出“值稳定”的假设其它与之无关的代码仍然可以被正常优化。在嵌入式编程中volatile最常见的使用场景是在中断与主循环之间传递状态信息。例如一个在中断回调中被置位、在主循环中被轮询的事件标志位就必须声明为volatile。否则在较高优化级别下编译器可能会认为该变量在主循环中从未被修改从而将读取操作提前、缓存甚至直接优化掉导致程序行为与预期严重不符。再从另一个角度看如果一个普通变量在同一执行路径中被连续写入不同的值但中间没有任何可观察行为依赖它那么在没有volatile的前提下编译器完全有理由认为这些写操作是“多余的”并将其消除。而一旦该变量被声明为volatile这些写操作就都变成了不可被消除的内存访问必须严格按顺序发生。需要特别强调的是volatile只解决编译器层面的可见性问题它并不保证原子性也不提供任何线程同步或内存顺序语义。对volatile变量的复合操作例如自增在中断或多线程环境中依然可能产生竞争条件。如果程序需要的是原子性或同步保证就必须借助关中断、锁、原子指令或专门的并发原语来实现。这就是为啥任何操作系统都要封装和提供锁的原语volatileuint32_t*constGPIO_IDR(volatileuint32_t*)0x40020010;// GPIO输入数据寄存器volatileuint8_tuart_rx_flag0;// 在中断中被修改的标志voidUART_IRQHandler(void){uart_rx_flag1;// 中断中修改}intmain(void){while(uart_rx_flag0){// 如果没有volatile编译器可能优化掉这个循环}}另外在访问硬件寄存器时通常需要同时使用volatile和const这个事情我相信读过SDK的朋友都知道的。#defineRCC_BASE0x40023800#defineRCC_AHB1ENR(*(volatileuint32_t*)(RCC_BASE0x30))// 可读可写的寄存器2. 运算符与表达式2.1 算术运算符C语言提供了标准的算术运算符但在嵌入式系统中使用时需要注意溢出和类型提升的问题inta10,b3;intsumab;// 加法13intdiffa-b;// 减法7intproducta*b;// 乘法30intquotienta/b;// 整数除法3截断intremaindera%b;// 取模1在嵌入式开发中除法和取模运算通常开销较大特别是在没有硬件除法器的MCU上。在性能关键的代码中应尽量避免除法运算或者用位移操作替代2的幂次的除法uint32_tvalue1024;uint32_tdiv_by_2value1;// 相当于 value / 2但更快uint32_tdiv_by_8value3;// 相当于 value / 82.2 位运算符位运算符是嵌入式编程的核心工具它们直接操作数据的二进制位常用于硬件寄存器配置、标志位管理和高效的数学运算。uint8_ta0b10110011;// 二进制字面量C23标准部分编译器支持uint8_tb0b11001010;// 按位与两位都为1时结果为1uint8_tand_resultab;// 0b10000010// 按位或任一位为1时结果为1uint8_tor_resulta|b;// 0b11111011// 按位异或两位不同时结果为1uint8_txor_resulta^b;// 0b01111001// 按位取反0变11变0uint8_tnot_result~a;// 0b01001100// 左移向左移动位右侧补0uint8_tleft_shifta2;// 0b11001100// 右移向右移动位uint8_tright_shifta2;// 0b00101100逻辑右移无符号数位运算在嵌入式开发中的典型应用包括寄存器位操作// 设置某一位#defineSET_BIT(reg,bit)((reg)|(1(bit)))// 清除某一位#defineCLEAR_BIT(reg,bit)((reg)~(1(bit)))// 切换某一位#defineTOGGLE_BIT(reg,bit)((reg)^(1(bit)))// 读取某一位#defineREAD_BIT(reg,bit)(((reg)(bit))1)// 示例配置GPIOSET_BIT(GPIOA-MODER,10);// 设置PA5的模式位CLEAR_BIT(GPIOA-ODR,5);// 清除PA5的输出位域掩码#defineSTATUS_READY0x01// 0b00000001#defineSTATUS_BUSY0x02// 0b00000010#defineSTATUS_ERROR0x04// 0b00000100#defineSTATUS_TIMEOUT0x08// 0b00001000uint8_tstatus0;status|STATUS_READY;// 设置就绪标志if(statusSTATUS_ERROR){// 检查错误标志// 处理错误}status~STATUS_BUSY;// 清除忙碌标志2.3 关系与逻辑运算符关系运算符用于比较返回整数结果0表示假非0表示真inta5,b10;intequal(ab);// 等于0intnot_equal(a!b);// 不等于1intless(ab);// 小于1intgreater(ab);// 大于0intless_equal(ab);// 小于等于1intgreater_equal(ab);// 大于等于0逻辑运算符具有短路特性这在嵌入式编程中可以用于条件优化// 逻辑与左侧为假时不评估右侧if(ptr!NULL*ptr0){// 安全检查防止空指针解引用// 处理}// 逻辑或左侧为真时不评估右侧if(error_flag||check_critical_condition()){// 当error_flag为真时不会调用函数}// 逻辑非if(!is_ready){// 等待就绪}2.4 其他重要运算符三元条件运算符是C语言中唯一的三元运算符可以简化简单的if-else语句intmax(ab)?a:b;// 等价于 if (a b) max a; else max b;// 在嵌入式中的应用uint8_tclamp(uint8_tvalue,uint8_tmin,uint8_tmax){return(valuemin)?min:((valuemax)?max:value);}sizeof运算符返回类型或对象的字节大小在编译时求值常用于数组大小计算uint32_tarray[10];size_tarray_sizesizeof(array);// 40字节假设uint32_t为4字节size_telement_countsizeof(array)/sizeof(array[0]);// 10个元素// 在嵌入式中用于缓冲区管理uint8_tbuffer[256];voidclear_buffer(void){memset(buffer,0,sizeof(buffer));}逗号运算符从左到右计算表达式返回最右边表达式的值intx(a5,ba10,b*2);// x 30// 在for循环中常见for(inti0,j10;ij;i,j--){// 同时更新两个变量}3. 控制流语句3.1 条件语句if-else语句是最基本的条件分支if(temperatureTEMP_HIGH_THRESHOLD){activate_cooling();}elseif(temperatureTEMP_LOW_THRESHOLD){activate_heating();}else{maintain_temperature();}在嵌入式系统中对于多个互斥条件使用else-if链可以避免不必要的条件检查提高执行效率。switch语句适用于多路分支编译器通常会将其优化为跳转表在某些情况下比多个if-else更高效switch(command){caseCMD_START:start_operation();break;caseCMD_STOP:stop_operation();break;caseCMD_PAUSE:pause_operation();break;caseCMD_RESUME:resume_operation();break;default:handle_unknown_command();break;}在嵌入式开发中switch语句常用于状态机实现typedefenum{STATE_IDLE,STATE_RUNNING,STATE_PAUSED,STATE_ERROR}SystemState;SystemState current_stateSTATE_IDLE;voidstate_machine_update(void){switch(current_state){caseSTATE_IDLE:if(start_button_pressed()){current_stateSTATE_RUNNING;initialize_operation();}break;caseSTATE_RUNNING:perform_operation();if(error_detected()){current_stateSTATE_ERROR;}elseif(pause_button_pressed()){current_stateSTATE_PAUSED;}break;caseSTATE_PAUSED:if(resume_button_pressed()){current_stateSTATE_RUNNING;}break;caseSTATE_ERROR:handle_error();if(reset_button_pressed()){current_stateSTATE_IDLE;}break;}}3.2 循环语句for循环通常用于已知迭代次数的情况// 传统for循环for(inti0;i10;i){array[i]i*i;}// 在嵌入式中常见的循环模式for(size_ti0;iARRAY_SIZE;i){process_element(array[i]);}// 无限循环在嵌入式主循环中常见for(;;){// 永远执行process_tasks();}while循环在条件未知或依赖于循环体内计算时使用while(uart_data_available()){uint8_tdatauart_read();process_data(data);}// 嵌入式中的典型等待循环while(!is_ready()){// 等待就绪}do-while循环至少执行一次循环体适用于某些初始化场景uint8_tretry_count0;do{resultattempt_communication();retry_count;}while(result!SUCCESSretry_countMAX_RETRIES);在嵌入式系统中无限循环是主程序的标准结构intmain(void){system_init();peripherals_init();while(1){// 或 for(;;)// 主循环read_sensors();process_data();update_outputs();handle_communication();}}3.3 跳转语句break语句用于提前退出循环或switch语句for(inti0;iMAX_ITEMS;i){if(items[i]target){found_indexi;break;// 找到目标退出循环}}continue语句跳过当前迭代的剩余部分继续下一次迭代for(inti0;idata_count;i){if(data[i]INVALID_VALUE){continue;// 跳过无效数据}process_valid_data(data[i]);}goto语句虽然常被批评但在嵌入式C中它在错误处理和资源清理场景中有合理的使用场景intinitialize_system(void){if(!init_hardware()){gotoerror_hardware;}if(!init_peripherals()){gotoerror_peripherals;}if(!init_communication()){gotoerror_communication;}returnSUCCESS;error_communication:cleanup_peripherals();error_peripherals:cleanup_hardware();error_hardware:returnERROR;}4. 函数函数笔者记得另一种叫法是子程序一个函数就是完成一段逻辑给人看的代码。从这个角度上C语言模块化编程的基础就是函数。我真见过一些朋友认为函数跳转是浪费时间的所以不该写函数——对但是后面不对因为显然不知道现代编译器会优化不必要的函数跳转而直接内联即直接向调用点安插片段节约压栈弹栈以及触发刷新流水线所消耗的时间此外你真的需要到这个地步以至于需要在乎函数跳转的时间嘛4.1 函数定义与声明// 函数声明原型intcalculate_checksum(constuint8_t*data,size_tlength);// 函数定义intcalculate_checksum(constuint8_t*data,size_tlength){intchecksum0;for(size_ti0;ilength;i){checksumdata[i];}returnchecksum0xFF;}4.2 函数参数传递C语言使用值传递但可以通过指针实现引用传递的效果// 值传递修改不影响原变量voidswap_wrong(inta,intb){inttempa;ab;btemp;}// 指针传递可以修改原变量voidswap_correct(int*a,int*b){inttemp*a;*a*b;*btemp;}// 使用intx10,y20;swap_correct(x,y);// x和y被交换在嵌入式开发中传递大型结构体时应使用指针以避免昂贵的拷贝typedefstruct{uint32_ttimestamp;floattemperature;floathumidity;uint16_tpressure;}SensorData;// 低效传递整个结构体voidprocess_data_inefficient(SensorData data){// 处理数据}// 高效传递指针voidprocess_data_efficient(constSensorData*data){// 处理数据使用data-temperature访问成员}4.3 内联函数现代的inline不再是内联函数的意思了——这一点各位再写C的时候必须注意他指代的是允许重复定义。因为他在一定程度上消灭了一个独立的符号编码从而回避了冲突——C编译器在现在也会主动的优化了。所以这个关键字如果您发现您的编译器真吃这个那就写否则不用写。// C99标准的内联函数staticinlineuint16_tswap_bytes(uint16_tvalue){return(value8)|(value8);}// 宏定义方式传统方法但类型不安全#defineSWAP_BYTES(x)(((x)8)|((x)8))4.4 函数指针与回调函数指针是实现回调的一个基本构件回调就是回头调用——就是这个意思。我们保存住函数的地址然后再需要的时候回头调用相当于我们将处理流存储了// 定义函数指针类型typedefvoid(*EventCallback)(void*context);// 回调注册系统typedefstruct{EventCallback callback;void*context;}EventHandler;EventHandler button_handler;voidregister_button_callback(EventCallback callback,void*context){button_handler.callbackcallback;button_handler.contextcontext;}// 在中断或主循环中调用voidhandle_button_event(void){if(button_handler.callback!NULL){button_handler.callback(button_handler.context);}}函数指针还可用于实现简单的多态笔者记得有一本不错的嵌入式C语言教程编写的基于C的多态的例子是不错的可惜忘记书名了汗typedefint(*MathOperation)(int,int);intadd(inta,intb){returnab;}intsubtract(inta,intb){returna-b;}intmultiply(inta,intb){returna*b;}intperform_operation(MathOperation op,intx,inty){returnop(x,y);}// 使用intresultperform_operation(add,10,5);// 15
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

网站关键词优化软件效果农产品网站建设

✅作者简介:热爱科研的Matlab仿真开发者,擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室🍊个人信条:格物致知,完整Matlab代码获取及仿真…

张小明 2025/12/31 4:21:54 网站建设

官方网站优化方法在线编辑图片的网站有哪些

第一章:GPU资源不足也能部署?Open-AutoGLM的轻量化破局之道在边缘计算和本地化部署需求日益增长的背景下,大模型的高显存占用成为落地瓶颈。Open-AutoGLM 通过一系列轻量化设计,使用户即便在仅有4GB显存的消费级GPU上也能高效运行…

张小明 2025/12/31 17:02:53 网站建设

兰溪网站建设学徒互联网怎么做

MPV配置优化指南:打造专业级视频播放体验 【免费下载链接】MPV_lazy 🔄 mpv player 播放器折腾记录 windows conf ; 中文注释配置 快速帮助入门 ; mpv-lazy 懒人包 win10 x64 config 项目地址: https://gitcode.com/gh_mirrors/…

张小明 2025/12/31 5:24:26 网站建设

玩具公司网站设计论文网站权重怎么查询

第一章:告别手动操作,Open-AutoGLM开启GUI自动化新纪元在现代软件开发与系统运维中,图形用户界面(GUI)的重复性操作已成为效率瓶颈。Open-AutoGLM应运而生,作为一款基于大语言模型驱动的GUI自动化框架&…

张小明 2025/12/31 17:02:57 网站建设

摄影网站规划设计书免费个人简历模板官网

EmotiVoice:让语音反馈充满“自豪感”的情感合成革命 在一款学习类App中,用户连续答对10道难题后,耳边传来一个熟悉又温暖的声音:“太棒了!你真的令人骄傲!”——这声音不仅语气饱满、充满喜悦,…

张小明 2025/12/31 17:02:58 网站建设

网站推广关键词营销型网站典型

在众多AI论文工具中,选择一款适合自己需求的平台可能令人眼花缭乱。本文将对比8款热门工具,重点聚焦降重、降AIGC率、写论文等功能。工具排名基于实测数据和用户反馈,确保客观实用性。以下是简要排行表(基于效率、准确性和易用性&…

张小明 2025/12/31 17:02:59 网站建设