慢 printf:为什么 __USE_MINGW_ANSI_STDIO=0 使它更快?

Rub*_*nks 10 c performance printf

我为 codeforces 中的一个问题编写了代码,尽管我相信我是在最佳时间复杂度下完成的,但它超出了第七个测试用例的时间限制。经过一些测试后,在我看来,大部分时间都被 printf 占用了,这似乎很奇怪,因为使用 printf 大约 3 * 10^5 次应该不是什么大问题。所以我搜索了很多,发现了这个:https://codeforces.com/blog/entry/105687#comment-940911
现在我得出的结论是,在代码顶部使用这一行将使 printf 更快:

#define __USE_MINGW_ANSI_STDIO 0
Run Code Online (Sandbox Code Playgroud)

因此,我运行了包含上述内容的代码,瞧,现在只包含一行代码就超过了 1 秒的时间限制,仅用了 62 毫秒就被接受了。我不理解链接中讨论的大部分其他内容,例如 MinGW 实现等。所以我的问题是,首先为什么它会这样工作?其次,从现在开始,我可以/应该在我在 codeforces 上的所有程序中继续使用上述代码行吗?

PS我还发现了这个博客:https://codeforces.com/blog/entry/47180 这对我来说太混乱了,暂时无法理解,但也许其他人可以理解它并阐明这个问题。

另外,这是codeforces问题:https://codeforces.com/contest/1774/problem/C 这是我的解决方案: https://codeforces.com/contest/1774/submission/185781891

我不知道整个输入,因为 codeforces 不共享它,而且它会非常非常大。但我知道输入到tests变量的值为3,输入到n[0]、n[1]、n[2]的值为100000、100000、100000

这是我的代码:

#define __USE_MINGW_ANSI_STDIO 0
#include <stdio.h>
#include <stdlib.h>
// #include <math.h>
// #include <string.h>

// #define lint long long int

// Function Declarations

int main(void)
{
    int tests;
    scanf("%i", &tests);
    int **answers = malloc(tests * sizeof(int*));
    int *n = malloc(sizeof(int) * tests);
    for (int i = 0; i < tests; i++)
    {
        scanf("%i", &n[i]);
        char *enviro = malloc((n[i]) * sizeof(int));
        answers[i] = malloc((n[i] - 1) * sizeof(int));
        int consec = 1; // No. of same consecutive elements at the very 
                        // end.
        scanf("%s", enviro);
        answers[i][0] = 1; // Case where x = 2;
        for (int x = 3; x < n[i] + 1; x++)
        {
            // comparing corresponding to current x vs previous x
            if (enviro[x - 2] == enviro[x - 3])
            {
                consec++;
            }
            else
            {
                 consec = 1;
            }
            answers[i][x - 2] = x - consec;
        }
        // Free loop variables
        free(enviro);
    }
    /* if (tests == 3)
    {
        printf("n[%i] = %i\n", i, n[i]);
    } */
    for (int i = 0; i < tests; i++)
    {
        for (int j = 0; j < n[i] - 1; j++)
        {
            printf("%i ", answers[i][j]);
        }
        printf("\n");
        free(answers[i]);
    }
    // Free variables
    free(answers);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编辑:所以我在codeforces( https://codeforces.com/contest/1774/submission/185788962 )上尝试了以下代码来解决相同的问题,只是为了查看执行时间:

// #define __USE_MINGW_ANSI_STDIO 0
#include <stdio.h>
#include <math.h>

int main(void)
{
    int n = pow(10, 5);
    for (int i = 0; i < n; i++)
    {
        printf("*");
    }
}
Run Code Online (Sandbox Code Playgroud)

如果没有 #define __USE_MINGW_ANSI_STDIO 0,则 et 为 374ms。有了它,它给了 15ms 的 et 。

jus*_*bie 10

看来 MinGW 定义了自己的printf()函数,__mingw_printf(). 这样做是为了修复某些旧 Windows 操作系统上的格式说明符问题,如其wiki中所示。__USE_MINGW_ANSI_STDIO如果您不想使用 MinGW 的实现,则将该宏设置为 0;如果您想使用,则将该宏设置为 1。

看起来 MinGW 的实现速度较慢,因此不使用它会使您的代码更快。

  • 甚至旧的 Windows 系统也不一定能从 MinGW 的 printf 实现中受益。事实上,当我使用 %zu 格式说明符时,我在 Windows 10 上的 MinGW 版本会抱怨,除非设置了此宏。 (3认同)