专业编程培训机构——完成蜕变以后轻松拿高薪
电话+V:159999-78052 ,欢迎咨询c语言编译错误如何快速定位,[python实用课程],[C++单片机原理],[C#网站搭建],[Nodejs小程序开发],[ios游戏开发],[安卓游戏开发],[教会用大脑用想法赚钱实现阶层跨越]
一、C语言编程后,有错误,怎么查看是那部分出错了!
【编写完代码后直接编译,如果有错误,编译器会自动弹出提示的】
例子如下:
如上图简单的C程序,编写完之后直接点击编译,然后会弹出错误信息,如下图所示:
修改错误之后,再次编译就可以得到正确的输出结果,如下图所示:
扩展资料:
C语言是一种计算机程序设计语言。它既有高级语言的特点,又具有汇编语言的特点。它可以作为系统设计语言,编写工作系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机硬件的应用程序。
C语言适用范围大。适合于多种操作系统,如Windows、DOS、UNIX、LINUX等等;也适用于多种机型。C语言对编写需要硬件进行操作的场合,明显优于其它高级语言,有一些大型应用软件也是用C语言编写的。
二、一段C语言代码不知道错哪儿了,请高手指教
程序中的错误,按照其产生的原因和引起的后果,通常可以分为三种类型:即语法错误、编译运行错误和逻辑错误。
一、语法错误
所谓“语法错误”是指由于违反了语言有关语句形式或使用规则而产生的错误。
比如错误地使用了关键字、遗漏了某些必需的标点符号、分支语句或循环语句不完整或不匹配等都会导致语法错误。
对于语法错误,在 VB 中可以通过设置“自动语法检测”功能来发现。设置“自动语法检测”功能的方法是执行菜单命令:工具︱选项, “编辑器”选项卡,然后再选中“自动语法检测”选项即可。
二、编译运行错误
程序运行时,当试图执行一个不能执行的操作时,会产生编译运行错误(也称运行时错误或实时错误),比如引用一个不存在的对象、进行除数为零的除法运算等都会产生运行时错误。
编译错误,一般是语法有问题,程序在编译是就产生错误不能编译成目标文件,比如包名或内部类名写错误等等。
运行错误,就是程序通过编译,却在运行时出错,一般是逻辑上的问题,比如数组越界,空指针等等。
比较常见的运行时错误是在做除法运算时所产生的“除数为零”错误。如下列 VB 代码:
1
C语言开发技巧笔记---如何在main函数前后运行自己的代码
首发2024-09-2312:06·stepwalker1.背景:
如果你想在一个软件项目中加入项目相关的特定信息,如:软件版本号,项目说明和描述信息,并希望这些信息在程序一开始即打印(运行在main函数之前),同时程序退出后能自动处理和销毁一些隐蔽的资源,这篇文章提到的方法可能会满足你的要求。这个特性通常用于在程序启动时执行一些全局的初始化工作,在程序结束时做一些资源清理的工作。2.示例代码:1)例程1:#include<stdio.h>#include<stdlib.h>__attribute((constructor))voidbefore_main(){printf("====%s=====",__FUNCTION__);}__attribute((destructor))voidafter_main(){printf("====%s=====",__FUNCTION__);}intmain(intargc,char**argv){printf("=====entering%s.========",__FUNCTION__);printf("====exitingfrommain!===");return0;}运行结果:说明:__attribute__是一个编译属性,用于向编译器描述特殊的标识、错误检查或高级优化。它是GNUC特色之一,系统中有许多地方使用到。__attribute__可以设置函数属性(FunctionAttribute)、变量属性(VariableAttribute)和类型属性(TypeAttribute)等。----__attribute((constructor)):告诉编译器,在程序加载时(在main函数执行之前),会自动调用这个函数;----__attribute((destructor)):告诉编译器,在程序结束后(在main函数执行之后),会自动调用这个函数;(2)例程2:#include<stdio.h>#include<stdlib.h>__attribute((constructor()))voidbefore_main(){printf("====%s=====:nopriority",__FUNCTION__);}__attribute((constructor(100)))voidbefore_main1(){printf("====%s=====:100",__FUNCTION__);}__attribute((constructor(101)))voidbefore_main2(){printf("====%s=====:101",__FUNCTION__);}__attribute((constructor(102)))voidbefore_main3(){printf("====%s=====:102",__FUNCTION__);}__attribute((destructor(102)))voidafter_main3(){printf("====%s=====102",__FUNCTION__);}__attribute((destructor()))voidafter_main(){printf("====%s=====nopriority",__FUNCTION__);}__attribute((destructor(100)))voidafter_main1(){printf("====%s=====100",__FUNCTION__);}__attribute((destructor(101)))voidafter_main2(){printf("====%s=====100",__FUNCTION__);}/////////////////////////////////////////////////////////////////intmain(intargc,char**argv){printf("=====entering%s.========",__FUNCTION__);printf("====exitingfrommain!===");return0;}运行结果:说明:1.constructor可以有优先级,指定优先级时,先执行优先级小的,再执行优先级大的,最后执行没有指定优先级。因此,在程序启动时,它们将按照before_main1->before_main2->before_main3->before_main的顺序执行。2.destructor也可指定优先级:但顺序刚好相反,先执行优先级的函数,再执行优先级最高的函数;如下:after_main-->after_main1-->after_main2-->after_main3;
(3)例程3:关于atexit函数的用法#include<stdio.h>#include<stdlib.h>staticvoidafter_main1(){printf("----%s---",__FUNCTION__);}staticvoidafter_main3(){printf("----%s---",__FUNCTION__);}staticvoidafter_main2(){printf("----%s---",__FUNCTION__);}//////////////////////////////////////intmain(intargc,char**argv){atexit(after_main1);atexit(after_main2);atexit(after_main3);printf("=======enteringmain=======");printf("=======leavingmain======");}运行结果:说明:1.atexit函数作用与上述__attribute__destructor类似,应该是对此特性封装的一个函数;2.执行时对调用顺序有很大的关系,遵循栈的特性,先进后出原则,后注册的函数先运行,因此上述执行顺序为:after_main3--->after_main2--->after_main1补充:进程终止的方式进程终止的方式有8种,前5种为正常终止,后3种为异常终止:1从main函数返回;2调?exit函数;3调?_exit或_Exit;4最后?个线程从启动例程返回;5最后?个线程调?pthread_exit;6调?abort函数;7接到?个信号并终?;8最后?个线程对取消请求做出响应。————————————————
3.__attribute__关健字的详细用法:1)section:自定义段section属性的主要作用是:在程序编译时,将一个函数或者变量放到指定的段,即指定的section中。一个可执行文件注意由代码段,数据段、bss段构成。代码段主要用来存放编译生成的可执行指令代码、数据段和bss段用来存放全局变量和未初始化的全局变量。#include<stdio.h>a.以下程序为编译器自动分配变量的段空间;#include<stdlib.h>intg_a=10;intg_b;intmain(intargc,char**argv){printf("====helloworld!==");}通过readelf工具可查看到g_a变量在.data段(index为25),g_b变量没有初始化放在.bss段(index为26);b.通过section关健字可指定section的位置:#include<stdio.h>#include<stdlib.h>intg_a=10;intg_b__attribute__((section(".data")));//指定放在.data段intmain(intargc,char**argv){printf("====helloworld!==");}~通过readelf工具可查看到g_b变量通过section设置后放在.data段(index为25);
2)aligned:字节对齐通过__attribute__来声明aligned和packed属性,指定一个变量或类型的对齐方式通过aligned属性,我们可以显示地指定变量在内存中的地址对齐方式。aligned有一个参数,表示要按几个字节对齐,使用时要注意,地址对齐的字节数必须是2的幂次方,否则编译就会报错。
3)packed:字节对齐aligned属性一般用来增大变量的地址对齐,元素之间地址对齐会造成一定的内存空洞,而packed属性则正好相反,一般用来减少地址对齐,指定变量或类型使用最可能小的地址对齐方式。---aligned修饰的是具体的变量,并不会改变结构体的内部成员的对齐方式,仅仅只是改变结构体所定义的变量地址对齐方式。---使用__attribute__((aligned(n))进行对齐声明,编译器通常会将所声明的对齐方式n与编译器默认的对齐方式进行比较,取最大值来进行对齐处理,---__attribute__((packed))是取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,也就是常说的采用1字节对齐的一种紧凑的对齐方式。---__attribute__((aligned(1))通常会采用系统默认的对齐方式,而__attribute__((packed))则会采用紧凑的1字节对齐方式。4)format:检查函数变参格式__attribute__((format(archetype,string-index,frist-to-check)))voidLOG(constchar*fmt,...)__attribute__((format(printf,1,2)));属性format(printf,1,2)有3个参数:第一个参数pritnf是告诉编译器,按照printf的标准来检查;第二个参数表示LOG()函数所有的参数列表中格式字符串的位置索引,第三个参数是告诉编译器要检查的参数的起始位置。
5)used:防止被编译器优化掉used的作用是告诉编译器,我声明的这个符号是需要保留的。被used修饰以后,意味着即使函数没有被引用,在Release下也不会被优化。如果不加这个修饰,那么Release环境链接器会去掉没有被引用的段。a.这个函数属性通知编译器在目标文件中保留一个静态函数,即使它没有被引用;b.标记为attribute__((used))的函数被标记在目标文件中,以避免链接器删除未使用的节;c.静态变量也可以标记为used,方法是使用attribute((used))。staticintlose_this(int);staticintkeep_this(int)__attribute__((used));//retainedinobjectfile6)unused表示该函数或变量可能不使用,这个属性可以避免编译器产生警告信息。#define__attribute_unused____attribute__((__unused__))7)at绝对定位绝对定位,可以把变量或函数绝对定位到Flash中,或者定位到RAM。定位到flash中,一般用于固化的信息,如出厂设置的参数,上位机配置的参数,ID卡的ID号,flash标记等等。constu16gFlashDefAddr[512]__attribute__((at(0x0800F000)))={0x1111,0x1111,0x1111,0x0111,0x0111,0x0111};//定位在flash中,其他flash补充为00constu16gflashdata__attribute__((at(0x0800F000)))=0xFFFF;8)constructor:确保函数在main函数被调用之前调用constructor和destructor会在ELF文件中添加两个段-.ctors和.dtors。当动态库或程序在加载时,会检查是否存在这两个段,如果存在执行对应的代码。9)destructor:确保函数在main函数被调用之后调用。10)weak:弱声明C语言强、弱符号,强、弱引用在项目开发的过程中,为了实现多平台兼容,增加代码的通用性,一般都是面向对象的设计思路;如果需要新增一个函数getTime,但是又不想影响到其他平台的使用,这个时候就需要弱引用。弱引用:有强引用优先编译强引用,没有则编译弱引用函数,避免编译报错;将一个函数和变量强符号,转换为弱符号。使用方法如下:void__attribute__((weak))func(void);intvariable__attribute__((weak));
弱符号的用途
1)、在一个源文件中引用一个编号或者函数,当编译器只看到声明,而没看到其定义时,一般编译时不会报错。在链接阶段,链接器会到其他文件中找到这些符号的定义,若未找到,则报未定义错误。
2)、当函数被声明一个弱符号时,会有一个奇特地方:当链接器找不到这个函数的定义时,也不会报错。编译器会将这个函数名,即弱符号,设置为0或者一个特殊值。只有当程序运行时,调用到这个函数,跳转到零地址或者一个特殊的地址才会报错误,产生一个内存错误。
3)、如果我们在使用函数前,判断这个函数地址是否为0,即可避免段错误。你会发现,即使函数未定义也可以正常编过。
4)、弱符号的这个特性在库函数开发设计中应用十分广泛,如果在开发一个库时,基础功能已经实现,有些高级功能还未实现,那么你就可以将这些函数通过weak属性声明转换为一个弱符号。
符号(或弱定义)weak属性只会在静态库(.o.a)中生效,动态库(.so)中不会生效11)alias:函数起别名主要用来给函数定义一个别名void__f(void){printf("__f");}voidf(void)attribute((alias(“__f”)));intmain(void){f();return0;}12)always_inline:内联函数总是展开inline仅仅是建议编译器内联,但不一定内联,always_inline强制内联。13)noinline:无内联与always_inline相反,无内联展开14)transparent_union我们可以使用透明联合类型,函数指针能够指向参数类型不同的函数。15)deprecated如果被变量或者函数的声明使用deprecated属性进行描述,那么编译器编译过程中不会产生警告或者错误,但是,被该属性描述的变量或者函数在其他地方被调用,那么编译会产生警告,警告信息中包含过时接口定义的位置及代码中的引用位置。#defineattribute_deprecated__attribute__((deprecated))/*VariableAttribute*/attribute_deprecatedintvariable_old=0;/*FunctionAttribute*/attribute_deprecatedvoidfunction_old(void);16)noreturn几个标注库函数,例如abortexit,没有返回值。GCC能够自动识别这种情况。noreturn属性指定像这样的任何不需要返回值的函数。当遇到类似函数还未运行到return语句就需要退出来的情况,该属性可以避免出现错误信息。【WINDRISES EMPLOYMENT PROGRAMMING】尊享对接老板
电话+V:159999-78052
机构由一批拥有10年以上开发管理经验,且来自互联网或研究机构的IT精英组成,负责研究、开发教学模式和课程内容。公司具有完善的课程研发体系,一直走在整个行业发展的前端,在行业内竖立起了良好的品质口碑。