我正在try 使用不同的C函数实现echo命令.通过printf实现它相当简单:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {
    while (--argc)
        printf(((argc == 1) ? "%s\n" : "%s "), *++argv);
}

这样做效果很好:

$ ./a.out Bring a towel
Bring a towel

但是,当我try 使用write系统调用实现它时:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    while (--argc) {
        write(STDOUT_FILENO, *++argv, strlen(*argv));
        write(STDOUT_FILENO, ((argc == 1) ? "\n" : " "), 1);
    }
}

它正在打印不正确长度的字符串:

$ ./a.out Bring a towel
Bringa atow t

我判断了strlen(*argv)printf返回的字符串长度,它们似乎正确.我也试过每write次用fflush(stdout)次冲洗.为什么我的write系统调用不能正常工作?

推荐答案

你的代码调用未定义的行为为the order of evaluation of function parameters is not specified.这里也没有序列点.此外,对argv本身的操作调用未定义的行为.

如果你重写你的程序:

int main(int argc, char *argv[]) {
    char **myargv = argv;
    while (--argc) {
        myargv++;
        write(STDOUT_FILENO, *myargv, strlen(*myargv));
        write(STDOUT_FILENO, ((argc == 1) ? "\n" : " "), 1);
    }
}

它会工作得很好

你可以通过修改你的原始程序来了解发生了什么.

int main(int argc, char *argv[]) {
    size_t index = 0;
    size_t len[10];
    while (--argc) {
        write(STDOUT_FILENO, *++argv, (len[index++] = strlen(*argv)));
        write(STDOUT_FILENO, ((argc == 1) ? "\n" : " "), 1);
    }
    for(size_t i = 0; i < index; i++)
    {
        printf("%zu\n", len[i]);
    }
}

您将看到,在和godbolt实现中,对strlen的第一次调用为您提供了argv[0]的长度.

C++相关问答推荐

char为16位且Short也为16位的c环境合法吗

如何将匿名VLA分配给指针?

想了解 struct 指针和空指针转换

Win32API Wizzard97 PropSheet_SetWizButton不工作

OpenSSL:如何将吊销列表与SSL_CTX_LOAD_VERIFY_LOCATIONS一起使用?

为什么Fread()函数会读取内容,然后光标会跳到随机位置?

类型定义 struct 与简单的类型定义 struct

如何在不使用字符串的情况下在c中编写函数atof().h>;

不确定如何处理此编译错误

不带Malloc的链表

从整型转换为浮点型可能会改变其值.

Matlab/Octave对conv2函数使用哪种方法?

如何打印循环调度问题的时间表

如果类型是新的,offsetof是否与typeof一起工作?

C 和 C++ 标准如何告诉您如何处理它们未涵盖的情况?

当另一个指向 const 的指针观察到数据时,通过指针更改数据是否安全?

C 语言中 CORDIC 对数的问题

free后内存泄漏?

为什么创建局部变量的指针需要过程在堆栈上分配空间?

int 与 size_t 与 long