Tag: 编译器构造

关于C函数原型和编译的问题

使用以下代码: int main(){ printf(“%f\n”,multiply(2)); return 0; } float multiply(float n){ return n * 2; } 当我尝试编译时,我得到一个警告:“’%f’期望’double’,但是参数的类型为’int’”和两个错误:“’multiply’的冲突类型”,“先前隐式声明’multiply’是这里。” 问题1 :我猜这是因为,鉴于编译器在第一次碰到它时不知道函数’multiply’,他将发明一个原型,发明原型总是假设’int’都被返回并被视为参数。 因此,本发明的原型将是“int multiply(int)”,因此也就是错误。 它是否正确? 现在,以前的代码甚至都不会编译。 但是,如果我打破两个文件中的代码,如下所示: #file1.c int main(){ printf(“%f\n”,multiply(2)); return 0; } #file2.c float multiply(float n){ return n * 2; } 并执行“gcc file1.c file2.c -o file”它仍然会发出一个警告(printf期望是double但是正在获取int)但是错误将不再显示并且它将被编译。 问题2 :为什么我将代码分成2个文件进行编译? 问题3 :一旦我运行上面的程序(版本分成2个文件),结果就是在屏幕上打印了0.0000。 怎么会? 我猜测编译器再次发明了一个与函数不匹配的原型,但为什么会打印0? 如果我将printf(“%f”)更改为printf(“%d”),它会打印1.再次,对幕后发生的事情的任何解释? 非常感谢提前。

使用Flex检测和跳过行注释

如何在Flex中检测到像“//”这样的一行注释并跳过此行? 并且: 如果使用下面的“/ *”注释即可。 它会起作用吗? “/*” { comment(); } %% comment() { char c, c1; loop: while ((c = input()) != ‘*’ && c != 0) putchar(c); if ((c1 = input()) != ‘/’ && c != 0) { unput(c1); goto loop; } if (c != 0) putchar(c1); }

编译背后的主要步骤是什么?

编译C程序的主要步骤是什么? 通过编译,我的意思是(可能是错误的)使用gcc从包含C代码的纯文本中获取二进制文件。 我很想了解这个过程的一些关键点: 到那天结束时,我需要将我的C代码转换为我的CPU应该理解的语言。 那么,谁在乎了解我的CPU特定指令呢? 操作系统? gcc是否将任何C转换为汇编语言? 我知道(实际猜测)对于每种处理器类型,我将需要一个汇编程序来解释(?)汇编代码并转换为我的CPU特定指令。 这个汇编程序(谁发货)在哪里? 它是否附带操作系统? 如果我用文本编辑器打开二进制文件,为什么我看不到0和1?

转换为另一种语言

代码可以转换的典型方法是什么? 目前,我正在编写一种简单的编程语言,它的处理方式是递归的。 循环的节点列表,并说当前节点是一个变量节点,它将调用emit_variable_node函数,它将字面上的一些代码附加到字符串,例如: 以下代码是psuedo-ish,我在C中编写我的项目,并编译为C. char *file_contents; void emit_variable_node(VariableNode *var) { // I know += doesn’t work on strings, just pretend it does. file_contents += var.getType(); file_contents += ” “; // a space file_contents += var.getName(); // etc } 我还假设我们给出的代码已经过语义分析,并且是正确的。 然后将file_contents字符串存储到临时文件中,该文件在由C编译器编译后删除。 这是一种不好的做法,还是有更好,更清洁的方法来做到这一点?

在GCC进行的每次优化后获取汇编代码?

来自维基百科上的优化编译器 , 编译器优化通常使用一系列优化转换来实现 ,这些算法采用程序并对其进行转换以生成使用较少资源的语义上等效的输出程序。 和GCC有很多优化选择。 我想在使用不同的标志(如-O1 , -O2 , -O3等)进行编译时执行每次优化后,研究生成的程序集(一个-S给出)。 我怎样才能做到这一点? 编辑:我的输入将是C代码。

使用`GCCs`预处理器作为汇编程序

有各种开源组装商,如gas , nasm和yasm 。 它们具有不同的pseudo-ops和macro语法。 对于许多开源项目,汇编程序经过预处理以替换常量和平台条件。 假设您可以使用所有当前attributes和#pragmas ,排除翻译性能(编译/汇编到二进制时间), gcc会创建汇编程序有什么限制? 我不是在谈论内联汇编 。 #define MOV(RA,RB) (OXFEB10000UL | RA << 16 | RB) #define ADD(RA,RB) (OXFEB20000UL | RA << 16 | RB) #define RET (OXFEB7ABCDUL) unsigned long add4[] __attribute(section(".text")) = { ADD(R0,R1), ADD(R2,R3), MOV(R1,R2), ADD(R0,R1), RET() }; 我相信使用指针算法可以进行模拟. 和其他labels 。 也许这是一个XY问题 ; 我试图理解为什么有这么多assembly工。 似乎所有事情都可以由预处理器完成,而汇编程序实际上是程序员的首选; 或者我缺少技术限制。 我想这可能与’你可以使用汇编程序做的事情有关,你无法用shell代码做’。 编辑:我已将其从C重新标记为编译器 。 […]

为什么模运算符是必要的?

我在一个文档中读到你可以用逻辑替换mod操作,如下所示: 代替: int Limit = Value % Range; 你做: int Limit = Value & (Range-1); 但编译器仍然生成mod指令,我的问题基本上是:为什么编译器如果工作相同,就不会使用最有效的方法?

gcc和turbo C的输出差异

为什么使用两个编译器gcc和turbo c编译代码时产生的输出有所不同。 #include int main() { char *p = “I am a string”; char *q = “I am a string”; if(p==q) { printf(“Optimized”); } else{ printf(“Change your compiler”); } return 0; } 我在gcc上得到了”Optimized” ,在turbo c上得到了”Optimized” “Change your compiler” 。 为什么?

C编译器可以重新排列堆栈变量吗?

我曾经在嵌入式系统的项目上工作,我们重新安排了堆栈变量声明的顺序,以减少生成的可执行文件的大小。 例如,如果我们有: void func() { char c; int i; short s; … } 我们会将此重新排序为: void func() { int i; short s; char c; … } 由于对齐问题,第一个导致使用12个字节的堆栈空间,第二个导致仅8个字节。 这是C编译器的标准行为,还是我们使用的编译器的缺点? 在我看来,编译器应该能够重新排序堆栈变量,以便在需要时支持更小的可执行文件大小。 有人向我建议,C标准的某些方面可以防止这种情况,但我无法以任何方式找到信誉良好的来源。 作为一个额外的问题,这也适用于C ++编译器吗? 编辑 如果答案是肯定的,那么C / C ++编译器可以重新排列堆栈变量,你能给出一个肯定会这样做的编译器的例子吗? 我想看看编译器文档或类似的东西支持这一点。 再次编辑 谢谢大家的帮助。 对于文档,我能够找到的最好的东西是GCC (pdf)中的最佳堆栈槽分配 ,由Naveen Sharma和Sanjiv Kumar Gupta撰写,于2003年在海湾合作委员会峰会会议上提交。 这里讨论的项目是使用ADS编译器进行ARM开发。 在该编译器的文档中提到,像我所示的排序声明可以提高性能以及堆栈大小,因为ARM-Thumb架构如何计算本地堆栈帧中的地址。 该编译器没有自动重新排列本地人以利用这一点。 这里链接的文章说,截至2003年,GCC也没有重新安排堆栈帧以改善ARM-Thumb处理器的参考局部性,但它暗示你可以。 我找不到任何明确说明在GCC中实施的内容,但我认为这篇论文可以certificate你是正确的。 再次感谢。

在编译时获取源文件的基本名称

我正在使用GCC; __FILE__返回当前源文件的完整路径和名称: /path/to/file.cpp 。 有没有办法在编译时获取文件的名称file.cpp (没有它的路径)? 是否可以以便携方式执行此操作? 模板元编程可以应用于字符串吗? 我在错误记录宏中使用它。 我真的不希望我的源代码完整路径进入可执行文件。