转帖:GCC编译器的常识

嵌入式C语言编译器:GCC 1 GCC相关介绍GCC与gcc有什么不同? GCC(GNU Compiler Collection) GNU编译器集合,包含众多语言的编译器:C、C++、Java、D、Objective-C、etc。 gcc:特指GCC中的C语言编译器 GCC VS 嵌入式 多数嵌入式操作系统都基于GCC进行源码编译 Linux、VxWorks、Android、etc。 实际开发中的应用 内核开发:gcc 阅读详情
在为Linux开发应用程序时,绝大多数情况下使用的都是C语言,因此几乎每一位Linux程序员面临的首要问题都是如何灵活运用C编译器。目前Linux下最常用的C语言编译器是GCC(GNU Compiler Collection),它是GNU项目中符合ANSI C标准的编译系统,能够编译用C、C++和Object C等语言编写的程序。GCC不仅功能非常强大,结构也异常灵活。最值得称道的一点就是它可以通过不同的前端模块来支持各种语言,如Java、Fortran、Pascal、Modula-3和Ada等。


开放、自由和灵活是Linux的魅力所在,而这一点在GCC上的体现就是程序员通过它能够更好地控制整个编译过程。在使用GCC编译程序时,
编译过程可以被细分为四个阶段:


◆ 预处理(Pre-Processing)

◆ 编译(Compiling)

◆ 汇编(Assembling)

◆ 链接(Linking)

Linux程序员可以根据自己的需要让GCC在编译的任何阶段结束,以便检查或使用编译器在该阶段的输出信息,或者对最后生成的二进制文件
进行控制,以便通过加入不同数量和种类的调试代码来为今后的调试做好准备。和其它常用的编译器一样,GCC也提供了灵活而强大的代码
优化功能,利用它可以生成执行效率更高的代码。

GCC提供了30多条警告信息和三个警告级别,使用它们有助于增强程序的稳定性和可移植性。此外,GCC还对标准的C和C++语言进行了大量
的扩展,提高程序的执行效率,有助于编译器进行代码优化,能够减轻编程的工作量。

GCC起步

在学习使用GCC之前,下面的这个例子能够帮助用户迅速理解GCC的工作原理,并将其立即运用到实际的项目开发中去。首先用熟悉的编辑
器输入清单1所示的代码:


清单1:hello.c

#include <stdio.h>




int main(void){
printf ("Hello world, Linux programming!/n");
   return 0;
}

然后执行下面的命令编译和运行这段程序:

# gcc hello.c -o hello
# ./hello
Hello world, Linux programming!

从程序员的角度看,只需简单地执行一条GCC命令就可以了,但从编译器的角度来看,却需要完成一系列非常繁杂的工作。首先,GCC需要
调用预处理程序cpp,由它负责展开在源文件中定义的宏,并向其中插入“#include”语句所包含的内容;接着,GCC会调用ccl和as将处理后的
源代码编译成目标代码;最后,GCC会调用链接程序ld,把生成的目标代码链接成一个可执行程序。

为了更好地理解GCC的工作过程,可以把上述编译过程分成几个步骤单独进行,并观察每步的运行结果。第一步是进行预编译,使用-E参数
可以让GCC在预处理结束后停止编译过程:

#  gcc -E hello.c -o hello.i


此时若查看hello.cpp文件中的内容,会发现stdio.h的内容确实都插到文件里去了,而其它应当被预处理的宏定义也都做了相应的处理。下一步
是将hello.i编译为目标代码,这可以通过使用-c参数来完成:

#  gcc -c hello.i -o hello.o


GCC默认将.i文件看成是预处理后的C语言源代码,因此上述命令将自动跳过预处理步骤而开始执行编译过程,也可以使用-x参数让GCC从指
定的步骤开始编译。最后一步是将生成的目标文件链接成可执行文件:

#  gcc hello.o -o hello


在采用模块化的设计思想进行软件开发时,通常整个程序是由多个源文件组成的,相应地也就形成了多个编译单元,使用GCC能够很好地管
理这些编译单元。假设有一个由foo1.c和foo2.c两个源文件组成的程序,为了对它们进行编译,并最终生成可执行程序foo,可以使用下面这条
命令:

#  gcc foo1.c foo2.c -o foo


如果同时处理的文件不止一个,GCC仍然会按照预处理、编译和链接的过程依次进行。如果深究起来,上面这条命令大致相当于依次执行如
下三条命令:

# gcc -c foo1.c -o foo1.o
# gcc -c foo2.c -o foo2.o
# gcc foo1.o foo2.o -o foo


在编译一个包含许多源文件的工程时,若只用一条GCC命令来完成编译是非常浪费时间的。假设项目中有100个源文件需要编译,并且每个源
文件中都包含10000行代码,如果像上面那样仅用一条GCC命令来完成编译工作,那么GCC需要将每个源文件都重新编译一遍,然后再全部连
接起来。很显然,这样浪费的时间相当多,尤其是当用户只是修改了其中某一个文件的时候,完全没有必要将每个文件都重新编译一遍,因
为很多已经生成的目标文件是不会改变的。要解决这个问题,关键是要灵活运用GCC,同时还要借助像Make这样的工具。

警告提示功能

GCC包含完整的出错检查和警告提示功能,它们可以帮助Linux程序员写出更加专业和优美的代码。先来读读清单2所示的程序,这段代码写得
很糟糕,仔细检查一下不难挑出很多毛病:

◆main函数的返回值被声明为void,但实际上应该是int;

◆使用了GNU语法扩展,即使用long long来声明64位整数,不符合ANSI/ISO C语言标准;

◆main函数在终止前没有调用return语句。

清单2:illcode.c

#include <stdio.h>
void main(void){
   long long int var = 1;
   printf("It is not standard C code!/n");
}


下面来看看GCC是如何帮助程序员来发现这些错误的。当GCC在编译不符合ANSI/ISO C语言标准的源代码时,如果加上了-pedantic选项,那
么使用了扩展语法的地方将产生相应的警告信息:

# gcc -pedantic illcode.c -o illcode
illcode.c: In function `main':
illcode.c:
9: ISO C89 does not support `long long'illcode.c:
8: return type of `main' is not `int'


需要注意的是,-pedantic编译选项并不能保证被编译程序与ANSI/ISO C标准的完全兼容,它仅仅只能用来帮助Linux程序员离这个目标越来越
近。或者换句话说,-pedantic选项能够帮助程序员发现一些不符合ANSI/ISO C标准的代码,但不是全部,事实上只有ANSI/ISO C语言标准中
要求进行编译器诊断的那些情况,才有可能被GCC发现并提出警告。

除了-pedantic之外,GCC还有一些其它编译选项也能够产生有用的警告信息。这些选项大多以-W开头,其中最有价值的当数-Wall了,使用它
能够使GCC产生尽可能多的警告信息:

# gcc -Wall illcode.c -o illcode
illcode.c:
8: warning: return type of `main' is not `int'illcode.c:
In function `main':illcode.c:
9: warning: unused variable `var'


GCC给出的警告信息虽然从严格意义上说不能算作是错误,但却很可能成为错误的栖身之所。一个优秀的Linux程序员应该尽量避免产生警告
信息,使自己的代码始终保持简洁、优美和健壮的特性。

在处理警告方面,另一个常用的编译选项是-Werror,它要求GCC将所有的警告当成错误进行处理,这在使用自动编译工具(如Make等)时非
常有用。如果编译时带上-Werror选项,那么GCC会在所有产生警告的地方停止编译,迫使程序员对自己的代码进行修改。只有当相应的警告
信息消除时,才可能将编译过程继续朝前推进。执行情况如下:

# gcc -Wall -Werror illcode.c -o illcodecc
1: warnings being treated as errorsillcode.c:
8: warning: return type of `main' is not `int'illcode.c:
In function `main':illcode.c:
9: warning: unused variable `var'


对Linux程序员来讲,GCC给出的警告信息是很有价值的,它们不仅可以帮助程序员写出更加健壮的程序,而且还是跟踪和调试程序的有力工
具。建议在用GCC编译源代码时始终带上-Wall选项,并把它逐渐培养成为一种习惯,这对找出常见的隐式编程错误很有帮助。

库依赖

在Linux下开发软件时,完全不使用第三方函数库的情况是比较少见的,通常来讲都需要借助一个或多个函数库的支持才能够完成相应的功
能。从程序员的角度看,函数库实际上就是一些头文件(.h)和库文件(.so或者.a)的集合。虽然Linux下的大多数函数都默认将头文件放
到/usr/include/目录下,而库文件则放到/usr/lib/目录下,但并不是所有的情况都是这样。正因如此,GCC在编译时必须有自己的办法来查找所需
要的头文件和库文件。

GCC采用搜索目录的办法来查找所需要的文件,-I选项可以向GCC的头文件搜索路径中添加新的目录。例如,如果在/home/xiaowp/include/目录
下有编译时所需要的头文件,为了让GCC能够顺利地找到它们,就可以使用-I选项:

# gcc foo.c -I /home/xiaowp/include -o foo

同样,如果使用了不在标准位置的库文件,那么可以通过-L选项向GCC的库文件搜索路径中添加新的目录。例如,如果在/home/xiaowp/lib/目录
下有链接时所需要的库文件libfoo.so,为了让GCC能够顺利地找到它,可以使用下面的命令:

# gcc foo.c -L /home/xiaowp/lib -lfoo -o foo


值得好好解释一下的是-l选项,它指示GCC去连接库文件libfoo.so。Linux下的库文件在命名时有一个约定,那就是应该以lib三个字母开头,由
于所有的库文件都遵循了同样的规范,因此在用-l选项指定链接的库文件名时可以省去lib三个字母,也就是说GCC在对-lfoo进行处理时,会自
动去链接名为libfoo.so的文件。

Linux下的库文件分为两大类分别是动态链接库(通常以.so结尾)和静态链接库(通常以.a结尾),两者的差别仅在程序执行时所需的代码是
在运行时动态加载的,还是在编译时静态加载的。默认情况下,GCC在链接时优先使用动态链接库,只有当动态链接库不存在时才考虑使用
静态链接库,如果需要的话可以在编译时加上-static选项,强制使用静态链接库。例如,如果在/home/xiaowp/lib/目录下有链接时所需要的库文
件libfoo.so和libfoo.a,为了让GCC在链接时只用到静态链接库,可以使用下面的命令:

# gcc foo.c -L /home/xiaowp/lib -static -lfoo -o foo

代码优化

代码优化指的是编译器通过分析源代码,找出其中尚未达到最优的部分,然后对其重新进行组合,目的是改善程序的执行性能。GCC提供的
代码优化功能非常强大,它通过编译选项-On来控制优化代码的生成,其中n是一个代表优化级别的整数。对于不同版本的GCC来讲,n的取值
范围及其对应的优化效果可能并不完全相同,比较典型的范围是从0变化到2或3。

编译时使用选项-O可以告诉GCC同时减小代码的长度和执行时间,其效果等价于-O1。在这一级别上能够进行的优化类型虽然取决于目标处
理器,但一般都会包括线程跳转(Thread Jump)和延迟退栈(Deferred Stack Pops)两种优化。选项-O2告诉GCC除了完成所有-O1级别的优化
之外,同时还要进行一些额外的调整工作,如处理器指令调度等。选项-O3则除了完成所有-O2级别的优化之外,还包括循环展开和其它一些
与处理器特性相关的优化工作。通常来说,数字越大优化的等级越高,同时也就意味着程序的运行速度越快。许多Linux程序员都喜欢使用-O2
选项,因为它在优化长度、编译时间和代码大小之间,取得了一个比较理想的平衡点。

下面通过具体实例来感受一下GCC的代码优化功能,所用程序如清单3所示。

清单3:optimize.c

#include <stdio.h> 


int main(void){
   double counter;
   double result;
   double temp;

   for (counter = 0; counter < 2000.0 * 2000.0 * 2000.0 / 20.0 + 2020; counter += (5 - 1) / 4) {
      temp = counter / 1979;
      result = counter;
   }

   printf("Result is %lf/n", result);
   return 0;
}


首先不加任何优化选项进行编译:

# gcc -Wall optimize.c -o optimize


借助Linux提供的time命令,可以大致统计出该程序在运行时所需要的时间:

# time ./optimize
Result is 400002019.000000
real 0m14.942s
user 0m14.940s
sys 0m0.000 s


接下去使用优化选项来对代码进行优化处理:

# gcc -Wall -O optimize.c -o optimize


在同样的条件下再次测试一下运行时间:

# time ./optimize
Result is 400002019.000000
real 0m3.256s
user 0m3.240s
sys 0m0.000s


对比两次执行的输出结果不难看出,程序的性能的确得到了很大幅度的改善,由原来的14秒缩短到了3秒。这个例子是专门针对GCC的优化功
能而设计的,因此优化前后程序的执行速度发生了很大的改变。尽管GCC的代码优化功能非常强大,但作为一名优秀的Linux程序员,首先还
是要力求能够手工编写出高质量的代码。如果编写的代码简短,并且逻辑性强,编译器就不会做更多的工作,甚至根本用不着优化。

优化虽然能够给程序带来更好的执行性能,但在如下一些场合中应该避免优化代码:

◆ 程序开发的时候 优化等级越高,消耗在编译上的时间就越长,因此在开发的时候最好不要使用优化选项,只有到软件发行或开发结束的时
候,才考虑对最终生成的代码进行优化。

◆ 资源受限的时候 一些优化选项会增加可执行代码的体积,如果程序在运行时能够申请到的内存资源非常紧张(如一些实时嵌入式设备),
那就不要对代码进行优化,因为由这带来的负面影响可能会产生非常严重的后果。

◆ 跟踪调试的时候 在对代码进行优化的时候,某些代码可能会被删除或改写,或者为了取得更佳的性能而进行重组,从而使跟踪和调试变得
异常困难。

调试

一个功能强大的调试器不仅为程序员提供了跟踪程序执行的手段,而且还可以帮助程序员找到解决问题的方法。对于Linux程序员来讲,GDB
(GNU Debugger)通过与GCC的配合使用,为基于Linux的软件开发提供了一个完善的调试环境。

默认情况下,GCC在编译时不会将调试符号插入到生成的二进制代码中,因为这样会增加可执行文件的大小。如果需要在编译时生成调试符
号信息,可以使用GCC的-g或者-ggdb选项。GCC在产生调试符号时,同样采用了分级的思路,开发人员可以通过在-g选项后附加数字1、2或3
来指定在代码中加入调试信息的多少。默认的级别是2(-g2),此时产生的调试信息包括扩展的符号表、行号、局部或外部变量信息。级别3
(-g3)包含级别2中的所有调试信息,以及源代码中定义的宏。级别1(-g1)不包含局部变量和与行号有关的调试信息,因此只能够用于回溯
跟踪和堆栈转储之用。回溯跟踪指的是监视程序在运行过程中的函数调用历史,堆栈转储则是一种以原始的十六进制格式保存程序执行环境
的方法,两者都是经常用到的调试手段。

GCC产生的调试符号具有普遍的适应性,可以被许多调试器加以利用,但如果使用的是GDB,那么还可以通过-ggdb选项在生成的二进制代码
中包含GDB专用的调试信息。这种做法的优点是可以方便GDB的调试工作,但缺点是可能导致其它调试器(如DBX)无法进行正常的调试。
选项-ggdb能够接受的调试级别和-g是完全一样的,它们对输出的调试符号有着相同的影响。

需要注意的是,使用任何一个调试选项都会使最终生成的二进制文件的大小急剧增加,同时增加程序在执行时的开销,因此调试选项通常仅
在软件的开发和调试阶段使用。调试选项对生成代码大小的影响从下面的对比过程中可以看出来:

# gcc optimize.c -o optimize
# ls optimize -l
-rwxrwxr-x 1 xiaowp xiaowp 11649 Nov 20 08:53 optimize (未加调试选项)
# gcc -g optimize.c -o optimize
# ls optimize -l
-rwxrwxr-x 1 xiaowp xiaowp 15889 Nov 20 08:54 optimize (加入调试选项)


虽然调试选项会增加文件的大小,但事实上Linux中的许多软件在测试版本甚至最终发行版本中仍然使用了调试选项来进行编译,这样做的目
的是鼓励用户在发现问题时自己动手解决,是Linux的一个显著特色。

下面还是通过一个具体的实例说明如何利用调试符号来分析错误,所用程序见清单4所示。

清单4:crash.c

#include <stdio.h> 
int main(void){
   int input =0;
   printf("Input an integer:");
   scanf("%d", input);
   printf("The integer you input is %d/n", input);
   return 0;
}


编译并运行上述代码,会产生一个严重的段错误(Segmentation fault)如下:

# gcc -g crash.c -o crash
# ./crash
Input an integer:10
Segmentation fault


为了更快速地发现错误所在,可以使用GDB进行跟踪调试,方法如下:

# gdb crashGNU 
gdb Red Hat Linux (5.3post-0.20021129.18rh)……
(gdb)


当GDB提示符出现的时候,表明GDB已经做好准备进行调试了,现在可以通过run命令让程序开始在GDB的监控下运行:

(gdb) run 
Starting program: /home/xiaowp/thesis/gcc/code/crash
Input an integer:10
Program received signal SIGSEGV, Segmentation fault.0x4008576b in _IO_vfscanf_internal () from /lib/libc.so.6


仔细分析一下GDB给出的输出结果不难看出,程序是由于段错误而导致异常中止的,说明内存操作出了问题,具体发生问题的地方是在调用
_IO_vfscanf_internal ( )的时候。为了得到更加有价值的信息,可以使用GDB提供的回溯跟踪命令backtrace,执行结果如下:

(gdb) backtrace
#0 0x4008576b in _IO_vfscanf_internal () from /lib/libc.so.6
#1 0xbffff0c0 in ?? ()
#2 0x4008e0ba in scanf () from /lib/libc.so.6
#3 0x08048393 in main () at crash.c:11
#4 0x40042917 in __libc_start_main () from /lib/libc.so.6


跳过输出结果中的前面三行,从输出结果的第四行中不难看出,GDB已经将错误定位到crash.c中的第11行了。现在仔细检查一下:

(gdb) frame 3
#3 0x08048393 in main () at crash.c:1111
scanf("%d", input);


使用GDB提供的frame命令可以定位到发生错误的代码段,该命令后面跟着的数值可以在backtrace命令输出结果中的行首找到。现在已经发现
错误所在了,应该将

scanf("%d", input);改为scanf("%d", &input);


完成后就可以退出GDB了,命令如下:

(gdb) quit


GDB的功能远远不止如此,它还可以单步跟踪程序、检查内存变量和设置断点等。

调试时可能会需要用到编译器产生的中间结果,这时可以使用-save-temps选项,让GCC将预处理代码、汇编代码和目标代码都作为文件保存起
来。如果想检查生成的代码是否能够通过手工调整的办法来提高执行性能,在编译过程中生成的中间文件将会很有帮助,具体情况如下:

# gcc -save-temps foo.c -o foo
# ls foo*foo foo.c foo.i foo.s


GCC支持的其它调试选项还包括-p和-pg,它们会将剖析(Profiling)信息加入到最终生成的二进制代码中。剖析信息对于找出程序的性能瓶颈
很有帮助,是协助Linux程序员开发出高性能程序的有力工具。在编译时加入-p选项会在生成的代码中加入通用剖析工具(Prof)能够识别的统
计信息,而-pg选项则生成只有GNU剖析工具(Gprof)才能识别的统计信息。

最后提醒一点,虽然GCC允许在优化的同时加入调试符号信息,但优化后的代码对于调试本身而言将是一个很大的挑战。代码在经过优化之
后,在源程序中声明和使用的变量很可能不再使用,控制流也可能会突然跳转到意外的地方,循环语句有可能因为循环展开而变得到处都
有,所有这些对调试来讲都将是一场噩梦。建议在调试的时候最好不使用任何优化选项,只有当程序在最终发行的时候才考虑对其进行优
化。
上次的培训园地中介绍了GCC的编译过程、警告提示功能、库依赖、代码优化和程序调试六个方面的内容。这期是最后的一部分内容。


加速

在将源代码变成可执行文件的过程中,需要经过许多中间步骤,包含预处理、编译、汇编和连接。这些过程实际上是由不同的程序负责完成
的。大多数情况下GCC可以为Linux程序员完成所有的后台工作,自动调用相应程序进行处理。

这样做有一个很明显的缺点,就是GCC在处理每一个源文件时,最终都需要生成好几个临时文件才能完成相应的工作,从而无形中导致处理
速度变慢。例如,GCC在处理一个源文件时,可能需要一个临时文件来保存预处理的输出、一个临时文件来保存编译器的输出、一个临时文
件来保存汇编器的输出,而读写这些临时文件显然需要耗费一定的时间。当软件项目变得非常庞大的时候,花费在这上面的代价可能会变得
很沉重。

解决的办法是,使用Linux提供的一种更加高效的通信方式—管道。它可以用来同时连接两个程序,其中一个程序的输出将被直接作为另一个
程序的输入,这样就可以避免使用临时文件,但编译时却需要消耗更多的内存。

在编译过程中使用管道是由GCC的-pipe选项决定的。下面的这条命令就是借助GCC的管道功能来提高编译速度的:

# gcc -pipe foo.c -o foo


在编译小型工程时使用管道,编译时间上的差异可能还不是很明显,但在源代码非常多的大型工程中,差异将变得非常明显。

文件扩展名

在使用GCC的过程中,用户对一些常用的扩展名一定要熟悉,并知道其含义。为了方便大家学习使用GCC,在此将这些扩展名罗列如下:


.c C原始程序;

.C C++原始程序;

.cc C++原始程序;

.cxx C++原始程序;

.m Objective-C原始程序;

.i 已经过预处理的C原始程序;

.ii 已经过预处理之C++原始程序;

.s 组合语言原始程序;

.S 组合语言原始程序;

.h 预处理文件(标头文件);

.o 目标文件;

.a 存档文件。

GCC常用选项

GCC作为Linux下C/C++重要的编译环境,功能强大,编译选项繁多。为了方便大家日后编译方便,在此将常用的选项及说明罗列出来如下:
 

-c 通知GCC取消链接步骤,即编译源码并在最后生成目标文件;

-Dmacro 定义指定的宏,使它能够通过源码中的#ifdef进行检验;

-E 不经过编译预处理程序的输出而输送至标准输出;

-g3 获得有关调试程序的详细信息,它不能与-o选项联合使用;

-Idirectory 在包含文件搜索路径的起点处添加指定目录;

-llibrary 提示链接程序在创建最终可执行文件时包含指定的库;

-O、-O2、-O3 将优化状态打开,该选项不能与-g选项联合使用;

-S 要求编译程序生成来自源代码的汇编程序输出;

-v 启动所有警报;

-Wall 在发生警报时取消编译操作,即将警报看作是错误;

-Werror 在发生警报时取消编译操作,即把报警当作是错误;

-w 禁止所有的报警。

小结

GCC是在Linux下开发程序时必须掌握的工具之一。本文对GCC做了一个简要的介绍,主要讲述了如何使用GCC编译程序、产生警告信息、调试程序和加快GCC的编译速度。对所有希望早日跨入Linux开发者行列的人来说,GCC就是成为一名优秀的Linux程序员的起跑线。 
 
深入Linux下的GCC编译器:从入门到精通 GCC最初作为GNU操作系统的官方编译器被开发,现在已经成为最流行的编译器之一。它被设计为可移植的,并且可以在多种架构上编译出高效的代码。GCC通过预处理器、编译器、汇编器和链接器四个阶段处理代码,将源代码转换成机器语言。在深入探讨静态和动态链接之前,我们首先需要了解链接的概念。链接是指在编译过程的最后阶段,编译器或链接器将各个编译单元(如目标代码、库文件等)合并为一个单一的可执行文件的过程。 阅读详情

相关推荐

GlobalPlatform Technology Secure Channel Protocol ‘03‘ 标准 - 安全通道协议简介

按照GlobalPlatform Technology Secure Channel Protocol '03' (SCP03)标准,描述了如何利用S-MAC,S-RMAC,S-ENC进行安全通信的过程。

mmmx777的专栏 6091

man fscanf scanf sscanf vfscanf vscanf vsscanf

名称 scanf, fscanf, sscanf, vscanf, vsscanf, vfscanf–格式化输入转换 概要 #include <stdio.h> int scanf(const char *format, ...); int fscanf(FILE *stream, const char *format, ...); int sscanf(const char *str, co...

li_huaqingfeng的博客 371

爬虫-Playwright逆向小红书

【代码】爬虫-Playwright逆向小红书。

weixin_44201223的博客 2430

GCC精彩之旅--转帖

作者:肖文鹏 发文时间:2004.03.22 在为Linux开发应用程序时,绝大多数情况下使用的都是C语言,因此几乎每一位Linux程序员面临的首要问题都是如何灵活运用C编译器。目前Linux下最常用的C语言编译器是GCC(GNU Compiler Collection),它是GNU项目中符合ANSI C标准的编译系统,能够编译用C、C++和Object C等语言编写的程序。GCC不仅功能非常强大

www.pingfi.com 1116

从零到一:3D Slicer与MONAI在医学影像中的AI革命

本文探讨了3D Slicer与MONAI在医学影像分析中的革命性应用,展示了如何通过开源工具实现高效的三维影像处理和AI增强分析。结合临床案例,详细介绍了从数据准备到AI分析的全流程,显著提升诊断效率和精度,推动医学影像技术迈向新纪元。

tcp8optimizer的博客 341

Altium Designer操作技巧(4)——如何利用嘉立创EDA来输出3D封装到AD封装库?

本文介绍了利用嘉立创EDA和FreeCAD软件为PCB元件添加3D模型的方法。首先在嘉立创EDA中搜索元件编号并导出3D模型,然后使用FreeCAD删除3D模型中的PCB基板部分,最后将处理后的3D模型导入PCB封装库并更新到PCB设计中。文章详细讲解了每个步骤的操作流程,包括模型导出、基板删除、位置调整等关键环节,并提供了解决常见问题的方法。通过这种方法,电子工程师可以快速获得元器件的3D模型,提高PCB设计的准确性。

u012526819的博客 2588

转贴:GCC编译器的常识

在为Linux开发应用程序时,绝大多数情况下使用的都是C语言,因此几乎每一位Linux程序员面临的首要问题都是如何灵活运用C编译器。目前Linux下最常用的C语言编译器是GCC(GNU Compiler Collection),它是GNU项目中符合ANSI C标准的编译系统,能够编译用C、C++和Object C等语言编写的程序。GCC不仅功能非常强大,结构也异常灵活。最值得称道的一点就...

diansu5840的博客 274

3篇1章6节:R基础绘图之图形的保存和导出技巧

高质量图形导出是R语言用户在数据分析和科研工作中的重要技能。通过合理控制图形的分辨率、选择合适的颜色管理方案和文件格式,以及掌握批量保存图形的技巧,可以显著提升图形的展示效果和应用范围。这不仅有助于提高研究成果的展示质量,还能在各种专业场合中展现数据分析的精确性和美观性。

MD Code 1481

VS使用scanf函数报错解决方法

Visual Studio中使用scanf函数会报错,因其安全性问题。解决方法有:1)改用scanf_s函数,需指定最大读取字符数;2)在项目属性中添加_CRT_SECURE_NO_WARNINGS预处理器定义;3)在代码开头添加宏定义#define _CRT_SECURE_NO_WARNINGS;4)使用#pragma warning(disable:4996)忽略警告。其中scanf_s更安全,能防止缓冲区溢出,而其他方法则是强制使用原scanf函数。

vbnetcx的博客 7万+

利用GAT(图论分析工具箱)构建并分析大脑结构协变网络学习笔记

前言 前面我学习了利用DTI构建白质纤维脑网络,并采用GRETNA计算了小世界网络属性。阅读文献发现可以利用灰质体积或皮层指标(皮层厚度、折叠指数、沟深)等构建结构协变网络再进行网络拓扑属性的计算。因此,我采用前面提取的灰质体积和皮质数据进行了结构协变网络分析,特此写下笔记以便后面的学习。 一、数据准备 二、构建结构协变网络 三、全局属性的统计分析 四、局部属性的统计分析 五、网络攻击分析 六、度的分布 ..................

weixin_52073820的博客 7497

Vue3 - 完美解决html2canvas截图不全问题,截图只截取当前可视区域导出图片不全,截屏导出的图片显示不全只有一部分或缺一块,vue3移动端H5网页项目使用html2canvas插件长截图!

vue3,html2canvas,移动端H5网页,截图不全,html2canvas长截图不全,保存长截图,页面滚动导致截图不全,网页下方截屏不到怎么办,底部一部分无法截屏到,保存的图片少了一大块,H5海报截图不完整,怎么截取滚动条下方的内容,截图图时图片不全,截图图片只有一半的问题,底部内容空白,截图空白问题的解决,截图不全怎么办,html2canvas.js网页截图功能(解决截图不全问题,移动端ios系统截图不完整,html2canvas截图太长又不能删减截取不到,使用HTML2Canvas在H5页面上实

🏆 前端领域优质创作者 1万+

glibc源码-libc_hidden_def

glibc版本:2.32 在阅读scanf源码的时候,看到ldbl_hidden_def,不明这个宏的意思,于是查阅资料,进行了一番了解。( 因为涉及的知识点太过庞大,包含链接,库的加载,函数的调用等等,且当前不从事与这方面的研究,故仅了解下) scanf调用:scanf->vfscanf->__vfscanf_internal. __vfscanf_internal的实现代码有2700行。。。。恐怖。浏览了一遍,没完全读懂,和vfprintf差不多,找到格式化字符,然后调用系统接口读入信

能别闹的博客 2534

作为专家系统与应用的审稿人:提醒你投稿注意事项

本文为《专家系统与应用》(ESWA)期刊投稿指南,重点强调研究方向匹配性、学术质量和写作规范。要求论文以智能系统/算法为核心,突出增量创新并具可验证性,需包含严谨方法论和充分实验验证。写作需结构清晰,符合期刊格式要求,包括明确的研究问题、分类文献综述、详细技术实现和量化结果。投稿前需仔细核对期刊指南,引用相关文献,并妥善处理审稿意见。ESWA注重创新实质性和应用落地价值,建议突出智能系统设计核心,避免成为单纯技术应用描述。

ZhangJiqun&191cm&85kg 1805

【C语言】GCC相关常识

【C语言】GCC相关常识

记录知识点的博客 1870

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

gcc编译器

1 gcc编译器简介 gcc 是 Linux 平台下最常用的编译程序,它是Linux 平台编译器的事实标准。同时,在 Linux 平台下的嵌入式开发领域,gcc也是用得最普遍的一种编译器。gcc 之所以被广泛采用,是因为它能支持各种不同的目标体系结构。例如,它既支持基于宿主的开发(简单讲就是要为某平台编译程序,就在该平台上编译),也支持交叉编译(即在 A 平台上编译的程序是供平台 B 使用的)。目前,gcc 支持的体系结构有四十余种,常见的有 X86 系列、Arm、PowerPC 等。同时,gc...

qq_34738528的博客 1万+

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

GCC编译器——GCC编译器安装教程

以下内容源于网络资源的整理,如有侵权请告知删除。

主要记录嵌入式学习与开发过程。 1万+

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

C语言编译器之一,GCC编译器

C语言作为高级语言,用其编写的程序指令机器并不能识别,因此需要有一个编译器将其转换为机器可识别的二进制指令。C语言已经出现50多年的时间,其相关的编译器种类众多,从最早先的turbo c系列编译器,到大名鼎鼎的gcc,还有基于LLVM的clang,各有优劣,而且在多个平台(如windows、Linux、MAC)上都广泛使用。同时由于Windows的强势存在,其自家的Visual C/C++编译器也有不少的应用。 一般C语言程序是在PC上编写,并将其编译成可执行文件,最终放到电脑或设备上去执行。

goodshanzi的博客 7054

【编译器GCC】

GCC(GNU Compiler Collection)是一套由 GNU 开发的编程语言编译器。它支持多种编程语言,包括 C、C++、Objective-C、Fortran、Ada 和 Go 等。

m0_74520482的博客 3665

Linux下的GCC编译器

GCC是GNU公社的一个项目,它是GNU Compiler Collection的缩写,起初,GCC只是一个C语言编译器(GNU C Collection),随着开发者的加入,GCC已扩展为可以编译C、C++、Java、Objective-C等多种编程语言的编译器集合了。如今的GCC也具有了交叉编译的功能,即在一个平台上编译另一个平台的代码。所谓编译器,可以简单地将其理解为“翻译器”。

asddrsq的博客 3206

GCC编译器——GCC编译器的简介

以下内容源于C语言中文网的学习与整理,如有侵权请告知删除。

主要记录嵌入式学习与开发过程。 6509

GCC编译器的常识

在为Linux开发应用程序时,绝大多数情况下使用的都是C语言,因此几乎每一位Linux程序员面临的首要问题都是如何灵活运用C编译器。目前Linux下最常用的C语言编译器是GCC(GNU Compiler Collection),它是GNU项目中符合ANSI C标准的编译系统,能够

mild_niu 952

【Linux】GCC编译器(七)

GCC的通用性使得它在不同的操作系统和平台上都能够使用,包括Linux、Unix、macOS等,这使得开发者可以使用同一套工具在不同的环境下进行开发,提高了开发的效率和一致性。除此之外,GCC已经成为了许多开发环境和工具链的标准组件,许多集成开发环境(IDE)和构建工具都提供了对GCC的支持,这使得开发者可以更轻松地使用GCC进行开发和构建。此外,GCC拥有丰富的功能和选项,支持多种编程语言,包括C、C++、Objective-C、Fortran等,可以满足各种不同项目的需求,从小型工具到大型软件项目。

hdz_wiz_csdn的博客 2371

VC编译器与GCC编译器的区别

首先,所谓语法区别是针对程序设计语言而言的,这里首先你要分清楚它们之间的区别。 Gcc:它是一款开源的C语言编译器,原来只能在Linux系统上使用,后来移植到了Windows操作系统上,以此为基础的编译环境典型的又MinGW。 它不是编程语言,所以没有语法这一说。G++:和GCC一个性质,只不过它是针对C++语言的。 VC:它有两种解释: 1.即VC本身,是微软公司推出的一款C++编译器,Visu...

江湖骇客 1万+

macOS CLion使用GCC编译器

第一步:安装CLion后,默认使用的是什么?在终端中直接输入gcc,得到如下结果: 上图说明,我们使用的是macOS自带的编译器。 当然,我们也有更加直观的方法来找到CLoin使用的是什么编译器。 使用CLoin新建工程,编写如下代码:#include <iostream> using namespace std; int main() { cout << __VERSION__

ShawnAtCSDB的博客 2万+

GCC编译器介绍

GCC编译器介绍

qq_44776454的博客 1426
上一篇: GNU GCC 手册(5)
下一篇: 用GCC编译程序
ShorminHsu
博客等级 码龄21年 59粉丝 60原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值