LCC解读笔记

本文介绍了一种基于缓冲区的文本读取方法,并详细解释了如何通过预处理指令进行文件和行号的处理,包括如何跳过空白字符、处理注释及特定预处理指令。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基础函数:

缓冲定义:

static unsigned char buffer[MAXLINE+1 + BUFSIZE+1];

MAXLINE是作为缓冲,当未处理完所有缓冲时,复制未读完的数据,在fillbuf可以看到应用。

获取下一行

 

  1. void nextline(void) {  
  2. do {  
  3. if (cp >= limit) {  
  4. fillbuf();  
  5. if (cp >= limit)  
  6. cp = limit;  
  7. if (cp == limit)  
  8. return;  
  9. else {  
  10. lineno++;  
  11. for (line = (char *)cp; *cp==' ' || *cp=='/t'; cp++)  
  12. ;  
  13. if (*cp == '#') {  
  14. resynch();  
  15. nextline();  
  16. }  
  17. }  
  18. while (*cp == '/n' && cp == limit);  
  19. }  
 

 

读取缓冲

 

  1. void fillbuf(void) {  
  2. if (bsize == 0)  
  3. return;  
  4. if (cp >= limit)  
  5. cp = &buffer[MAXLINE+1];  // 读完  
  6. else  
  7. // 未读完  
  8. int n = limit - cp;  
  9. unsigned char *s = &buffer[MAXLINE+1] - n;  
  10. assert(s >= buffer);  
  11. line = (char *)s - ((char *)cp - line);  
  12. while (cp < limit)  
  13. *s++ = *cp++;  
  14. cp = &buffer[MAXLINE+1] - n;  
  15. }  
  16. if (feof(stdin))  
  17. bsize = 0;  
  18. else  
  19. bsize = fread(&buffer[MAXLINE+1], 1, BUFSIZE, stdin); // 读文件到缓冲  
  20. if (bsize < 0) {  
  21. error("read error/n");  
  22. exit(EXIT_FAILURE);  
  23. }  
  24. limit = &buffer[MAXLINE+1+bsize];    // 设置缓冲尾部  
  25. *limit = '/n';  
  26. }  
 

 

输入初始化

 

  1. void input_init(int argc, char *argv[]) {  
  2. static int inited;  
  3. if (inited)  
  4. return// 只初始化一次  
  5. inited = 1;  
  6. main_init(argc, argv); // 主初始化  
  7. limit = cp = &buffer[MAXLINE+1];  
  8. bsize = -1;  
  9. lineno = 0;  
  10. file = NULL;  
  11. fillbuf();  
  12. if (cp >= limit)  
  13. cp = limit;  
  14. nextline(); // 读一行  
  15. }  
  16.   
  17.   
  18. iden预处理  
  19. static void ident(void) {  
  20. while (*cp != '/n' && *cp != '/0')  
  21. cp++;  
  22. }  
 

 

预处理

 

  1. /* resynch - set line number/file name in # n [ "file" ], #pragma, etc. */  
  2. static void resynch(void) {  
  3. for (cp++; *cp == ' ' || *cp == '/t'; )  
  4. cp++;  
  5. if (limit - cp < MAXLINE)  
  6. fillbuf();  
  7. if (strncmp((char *)cp, "pragma", 6) == 0) {  
  8. cp += 6;  
  9. pragma();  
  10. else if (strncmp((char *)cp, "ident", 5) == 0) {  
  11. cp += 5;  
  12. ident();  
  13. else if (*cp >= '0' && *cp <= '9') {  
  14. line:   for (lineno = 0; *cp >= '0' && *cp <= '9'; )               // #line 处理,记录文件名以及修正行数  
  15. lineno = 10*lineno + *cp++ - '0';  
  16. lineno--;  
  17. while (*cp == ' ' || *cp == '/t')  
  18. cp++;  
  19. if (*cp == '"') {  
  20. file = (char *)++cp;  
  21. while (*cp && *cp != '"' && *cp != '/n')  
  22. cp++;  
  23. file = stringn(file, (char *)cp - file);  
  24. if (*cp == '/n')  
  25. warning("missing /" in preprocessor line/n");  
  26. if (firstfile == 0)  
  27. firstfile = file;  
  28. }  
  29. else if (strncmp((char *)cp, "line", 4) == 0) {  
  30. for (cp += 4; *cp == ' ' || *cp == '/t'; )  
  31. cp++;  
  32. if (*cp >= '0' && *cp <= '9')  
  33. goto line;  
  34. if (Aflag >= 2)  
  35. warning("unrecognized control line/n");  
  36. else if (Aflag >= 2 && *cp != '/n')  
  37. warning("unrecognized control line/n");  
  38. while (*cp)  
  39. if (*cp++ == '/n')  
  40. if (cp == limit + 1) {  
  41. nextline();  
  42. if (cp == limit)  
  43. break;  
  44. else  
  45. break;  
  46. }  
 

 

03-20
### LCC 编译器的使用与错误处理 LCC 是一种可重定位的 C 编译器,其设计旨在支持多种目标架构并提供灵活的移植能力[^1]。它通过模块化的设计实现了高效的代码生成以及良好的跨平台兼容性。 #### 错误处理机制 在编译过程中,LCC 的错误处理主要体现在以下几个方面: 1. **语法错误检测** 当输入的源码不符合 C 语言语法规则时,LCC 能够识别这些错误并向用户提供详细的诊断信息。例如,在解析函数声明的过程中,如果发现参数列表不匹配或者缺少必要的关键字,则会触发相应的错误提示[^3]。 2. **语义错误检查** 此外,LCC 还会对程序中的逻辑一致性进行验证。比如,当遇到未定义的变量、类型冲突等问题时,编译器能够及时报告这些问题,并指出具体的行号以便开发者快速定位问题所在[^4]。 3. **运行时错误预防** 尽管 LCC 主要关注的是静态分析阶段的错误捕捉,但它也间接帮助减少潜在的运行时崩溃风险。这得益于其严格的类型系统和边界条件审查机制。 #### 使用场景下的注意事项 对于希望利用 LCC 来开发项目的工程师来说,了解如何正确配置环境至关重要。通常情况下,安装完成后可以通过命令行调用该工具链完成从源文件到最终执行体的构建流程。值得注意的一点是,由于不同版本之间可能存在功能差异,因此建议查阅官方文档获取最新指导说明。 另外,在实际应用当中还需要注意以下几点: - 确保所依赖的标准库路径已被正确设置; - 如果项目涉及到外部接口调用的话,则需额外指定相应头文件位置及相关链接选项; - 针对特定硬件特性定制优化策略时应充分考虑性能开销与维护成本之间的平衡关系[^2]。 ```c // 示例:简单的 Hello World 应用及其可能引发的常见错误演示 #include <stdio.h> int main() { printf("Hello, world!"); // 忘记添加换行符可能导致后续调试困难 // 或者与其他输出混杂在一起难以阅读 return; // 返回值缺失也会被标记为警告甚至错误视乎编译选项而定 } ``` 上述例子展示了两个容易忽略的小细节——忘记加入 `\n` 和省略 `return` 表达式的完整形式。虽然看似无害,但在某些严格模式下它们都足以阻止进一步操作直至修复完毕为止。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值