【问题标题】:Why is putchar() writing a new line in this simple code?为什么 putchar() 在这个简单的代码中写一个新行?
【发布时间】:2020-10-15 02:41:33
【问题描述】:

我不明白为什么在我运行这个程序时会向标准输出写入过多的空白。

int main(int argc, char **argv)
{
    argv++;

    for (int i = 0; i < argc - 1; i++)
    {
        for (int j = 0; j < strlen(*argv); j++)
        {
            putchar(*(*(argv + i) + j));
        }
        printf("\n");
    }
    
}

输出:

(base) benjamin@benjamin-G5-5587:~$ ./uecho hello world baby yoyoyo                           
hello                                                                                         
world                                                                                         
baby                                                                                          
         //whitespace?                                                                                     
yoyoy  

【问题讨论】:

  • 更不明白为什么'yoyoyo'的最后一个字符没有写!

标签: c putchar


【解决方案1】:

您的内部循环条件错误,导致您读取越界。它始终受到第一个参数strlen(*argv) 的限制(感谢之前的argv++),即使在处理第二个和后续参数时也是如此。由于您读出了"hello" 的长度,因此您过度阅读了"baby",并且未能阅读所有"yoyoyo"。将baby 过度读取一个字符最终会将NUL 写入stdout,我猜您的终端正在以类似于换行符的方式进行解释。

我建议:

  1. 解决问题,以便您使用每个参数的长度来打印它,并且
  2. 用简单的数组索引语法代替难以理解的指针算法

最终结果如下所示:

int main(int argc, char **argv)
{
    for (int i = 1; i < argc; i++)  // Adjust bounds to loop over provided args without mucking with argv directly
    {
        for (int j = 0; j < strlen(argv[i]); j++)  // Loop to length of current arg
        {
            putchar(argv[i][j]);
        }
        printf("\n");
    }
}

【讨论】:

  • 感谢您的回复!我很好奇你是否知道学习指针算术是否有任何优势,而不是更易读的括号符号?
  • @BenJenney:学习它是很有用的,可以作为开发计算机如何实际实现更高层次结构的基础的一部分。但是在实际代码中实际使用它并没有什么好处。在优化器较差的旧编译器中,它可能会提高性能;在启用了优化的现代编译器中,它们几乎可以一直自己进行转换,并且在某些情况下,当它们具有使用公共变量的逻辑上下文索引时,可以实现更好的性能,因为单独指针上的算术不会.
  • 我认为我有一个真正的指针算法用例,它实际上提供了一些好处,即使这样它也是可疑的(只是通过分配单个连续块来改善缓存局部性的廉价黑客表示不连续数据的内存,指针算法用于计算每个逻辑连续块的基指针)。我使用了与mmap 反向的类似技巧,将一堆(多页长度)文件背靠背放入连续地址(因此 1000 个文件看起来像一个大数组),这对于相关用例来说很方便。
  • 在这两种情况下,它都很聪明,而且编写起来很有趣(mmap 的情况实际上显着简化了代码,同时通过避免急切地吞食文件来缩短启动时间),但实际性能收益微乎其微。
猜你喜欢
  • 1970-01-01
  • 2015-02-19
  • 2012-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-18
  • 2013-05-04
相关资源
最近更新 更多