标签: compiler-explorer

为什么 MSVC C++ 编译器将一个简单的 Hello World 扩展为 4000 行汇编代码?

最近,我正在深入优化我的 C++ 代码,因此开始尝试使用编译器资源管理器。由于我主要使用 Visual Studio 在 Windows 上进行开发,因此我使用了 msvc 编译器。

在某些时候 msvc 失控了。经过一番摆弄之后,我可以将其缩小到 iostream 标头,这应该是 I/O ( SL.io.3 ) 的首选。

#include <iostream>
int main() {
    std::cout << "Hello World!\n";
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

而 gcc 或 clang 的总输出(main + 一个调用一些ios_baseinit 函数的静态初始化器)总共有大约 20 行汇编代码(在 Godbolt 编译器浏览器过滤掉指令和注释之后)。
MSVC 将其分解为 4000。这些行中的大多数是单独的函数;MSVC 对main自身的定义是 7 条指令,而 gcc/clang 则是 8 条指令。(使用 GNU/Linux 的 gcc/clanglibstdc++将额外长度的 arg 传递给 cout 运算符重载函数,而不是像 MSVC 在使用自己的 C++ 库时那样只传递 2 个指针。)

如果我使用类似的东西puts,MSVC 的总输出相当紧凑,可与 gcc/clang 相媲美,就像 …

c++ assembly visual-studio visual-c++ compiler-explorer

12
推荐指数
1
解决办法
776
查看次数

Godbolt 不显示标准输出

我正在使用https://godbolt.org/编译一个简单的 C++ 脚本,但即使是最简单的

int main()
{
  std::cout << "Hello World!" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

当我点击时Add new... --> Compiler --> Output我得到:Compiler returned: 0

c++ compiler-explorer godbolt

12
推荐指数
1
解决办法
1万
查看次数

如何使用 Godbolt(编译器资源管理器)测试 C++ 模块?

为了在 C++20 中使用自编模块提出问题或演示错误/功能,能够使用Matt Godbolt 的编译器资源管理器会很棒。

例子:

test.cpp(模块测试):

export module test;

export template<typename T>
void do_something(const T&)
{
}
Run Code Online (Sandbox Code Playgroud)

编译 clang++ -std=c++20 -stdlib=libc++ -fmodules -c -Xclang -emit-module-interface -o test.pcm test.cpp

主.cpp:

import test;

int main() {
    do_something(7);
}
Run Code Online (Sandbox Code Playgroud)

编译 clang++ -std=c++20 -stdlib=libc++ -fmodules -fimplicit-modules -fimplicit-module-maps -fprebuilt-module-path=. main.cpp

问:有没有办法用编译器资源管理器来做到这一点?

c++ c++20 c++-modules compiler-explorer

11
推荐指数
1
解决办法
1189
查看次数

C++ 中 HTTP URL 的 #include

我在 Github 上查看了一个随机 C++ 示例(https://github.com/Quuxplusone/coro/blob/master/examples/pythagorean_triples_generator.cpp),并惊讶地发现它实际上可以编译(https://coro.cpp)。 godbolt.org/z/JXTX4Y)。

#include <https://raw.githubusercontent.com/Quuxplusone/coro/master/include/coro/shared_generator.h>
#include <stdio.h>
#include <tuple>
#include <range/v3/view/take.hpp>

namespace rv = ranges::view;

auto triples() -> shared_generator<std::tuple<int, int, int>> { 
    for (int z = 1; true; ++z) {
        for (int x = 1; x < z; ++x) {
            for (int y = x; y < z; ++y) {
                if (x*x + y*y == z*z) {
                    co_yield std::make_tuple(x, y, z);
                }
            }
        }
    }
}

int main() {
    for (auto&& triple : …
Run Code Online (Sandbox Code Playgroud)

c++ c++11 c++17 c++20 compiler-explorer

9
推荐指数
1
解决办法
1794
查看次数

高性能“适当”的 C++ 替代可变长度数组

我正在编写一个需要在运行时创建数组的函数。该数组将是小尺寸,因此我不担心不安全的代码,但是,我想编写“正确”的代码。因此,我正在考虑三种选择:

  1. 字符数组[len];
  2. 字符数组 = 新字符(len);
  3. std::vector 数组(len);

使用Compiler Explorer将它们与 -O3 进行比较。结果如下:

  1. 12条指令,0次调用new
  2. 21条指令,1次调用new
  3. 118 条指令,2+ 次调用 new

我是否错过了对 std::vector<> 的优化,或者“正确的”C++ 方式是否较慢,或者我完全错过了一种编码方式?

编辑:我忘了删除堆分配的数组

测试代码:

代码1:

#include <string.h>

void populate_array(char* arr);
int compute_result(char* arr);

int str_to_arr(const char* str)
{
    auto len = strlen(str);
    char array[len];
    populate_array(array);
    return compute_result(array);
}
Run Code Online (Sandbox Code Playgroud)

代码2:

#include <string.h>

void populate_array(char* arr);
int compute_result(char* arr);

int str_to_arr(const char* str)
{
    auto len = strlen(str);
    char* array = new char[len];
    populate_array(array);
    auto result = compute_result(array);
    delete[] array;
    return …
Run Code Online (Sandbox Code Playgroud)

c++ arrays compiler-explorer

8
推荐指数
1
解决办法
474
查看次数

如何在本地生成像干净组装一样的godbolt?

我想在本地生成像编译器资源管理器这样的干净程序集。请注意,我阅读了如何从 GCC/clang 程序集输出中删除“噪音”?在尝试之前。与 Godbolt 相比,使用该方法的输出没有那么干净或密集,并且仍然有很多 asm 指令和未使用的标签。

如何在没有任何未使用的标签或指令的情况下获得干净的汇编输出?

c++ assembly gcc clang compiler-explorer

6
推荐指数
2
解决办法
1811
查看次数

如何在GCC trunk中使用&lt;stacktrace&gt;?

https://github.com/gcc-mirror/gcc/commit/3acb929cc0beb79e6f4005eb22ee88b45e1cbc1d提交来看,C++ 标准头<stacktrace>存在诸如此类的东西,std::stacktrace_entry但没有声明,因为_GLIBCXX_HAVE_STACKTRACE也没有定义。

我已经在https://godbolt.org/z/b9TvEMYnh上尝试过,但是一旦我添加了参数,就会发出链接器错误-lstd++_libbacktrace(ofc,未找到)

#include <stacktrace> // header found

int main() {
  // can't use features like 'std::stacktrace_entry' and 'std::stacktrace'
}
Run Code Online (Sandbox Code Playgroud)

从提交描述来看,这条消息意味着什么?:

目前,只有使用 --enable-libstdcxx-backtrace=yes 时才会构建新库。

c++ libstdc++ compiler-explorer c++23

4
推荐指数
1
解决办法
1782
查看次数

我可以将自己的汇编文件/指令添加到 godbolt 项目中吗?

正如标题所示。比如说,我想通过Godbolt项目来做到这一点:

main.cpp

#include <iostream>

extern "C" int test_111();

int main()
{
    int r = test_111();
    
    std::cout << "result=" << r << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

然后在asm1.asm

.code

test_111 PROC

    ; 64-bit assembly
    xor eax, eax
    inc rax

    ret

test_111 ENDP

END
Run Code Online (Sandbox Code Playgroud)

在“x86-64 clang”(任何版本)下尝试。

但我似乎不知道如何做到这一点。有什么建议么?

附言。目标是将我自己的汇编指令注入到输出中。


编辑:

在评论中提出建议后,我尝试了关键词asm volatile,但它只是将我放入其中的任何乱码添加到程序集输出中:

在此输入图像描述

c++ assembly clang compiler-explorer

3
推荐指数
1
解决办法
199
查看次数

在编译器资源管理器中包含 C 的外部头文件

我想在编译器资源管理器 (godbolt.org) 上运行一个 C 项目,其中包含一些外部头文件。包含这些第三方头文件的过程是什么?

项目截图

假设我想运行包含 snipmath.h 文件的代码。此外,snipmath.h 标头还包含其他 lib 文件。我怎样才能将它们全部包含在 godbolt 中?就像我们通常在离线编译器中所做的那样。

c header compiler-explorer godbolt

2
推荐指数
1
解决办法
4682
查看次数

std::convertible_to 无法识别显式可转换类型

根据convertible_to中的 en.cppreference.com :

概念convertible_to<From, To>指定与std::declval()相同类型和值类别的表达式可以隐式和显式转换为To类型,并且两种转换形式是等效的。

我理解这意味着如果有成员,该convertible_to概念将被识别convertible_to<U, V>为满意。即使运算符是显式的而不是隐式运算符。Uexplicit operator V()

但是我发现msvc中不是这样的。

由于静态断言,以下代码无法编译:

#include <concepts>
#include <iostream>

class ExplictClass
{
public:
    inline explicit operator int() const
    {
        return 5;
    }
};

int main()
{
    static_assert(std::convertible_to<ExplictClass, int>, "Explicit not convertible?"); // Fails here, concept not satisfied.
}
Run Code Online (Sandbox Code Playgroud)

这是我对概念的误解std::convertible_to,代码中的错误,还是 en.cppreference.com 中的错误,或者 msvc v19 的不一致性。

附上使用 x64 msvc v19.latest 的编译器资源管理器的链接,其中包含上述代码

编译器浏览器

编辑:

实际需要convertible_to是生成一个to_string函数模板,该模板可以与声明的可转换类型很好地配合,如下所示:

template<class T>
std::string to_string(T val)
{
    std::ostringstream stream; …
Run Code Online (Sandbox Code Playgroud)

c++ c++-concepts c++20 compiler-explorer

2
推荐指数
1
解决办法
274
查看次数