小编Eri*_*tch的帖子

如何使用 clang 编译 avr (arduino)

当我搜索时,我发现 7 年前的结果谈论的是 clang 的叉子而不是 clang 本身。

使用 avr-gcc 我可以编译并上传我的代码

avr-gcc a.cpp -DF_CPU=16000000 -mmcu=atmega2560 -Wall -Werror -Wextra -Os
avr-objcopy -j .text -j .data -O ihex a.out my.hex
sudo avrdude -patmega2560 -cwiring -P/dev/ttyACM0 -b115200 -D -Uflash:w:my.hex:i
Run Code Online (Sandbox Code Playgroud)

我想用 替换第一步clang++。我在这里所做的更改

  • avr-gcc 到 clang++
  • 添加--target=avr
  • 添加是-nostdlib因为我会自己添加它
  • 添加是-I/usr/avr/include/因为路径不是隐式的
  • 已添加-L/usr/avr/lib/avr6 -lc -latmega2560,因此它有足够的信息来构建精灵

我在 /usr/lib/gcc/avr/10.2.0/device-specs/specs-atmega2560 找到了设备规格,其中提到crtatmega2560.o并且-latmega2560似乎位于/usr/avr/lib/avr6/. 所以我想出了以下内容并得到了这些错误。我应该如何编译才能使用 avrdude 获取十六进制上传?

$ clang++ a.cpp -DF_CPU=16000000 -mmcu=atmega2560 -Wall -Werror -Wextra -Os --target=avr -I/usr/avr/include/ -nostdlib -L/usr/avr/lib/avr6 …
Run Code Online (Sandbox Code Playgroud)

avr arduino clang

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

为什么排序会使这个无分支代码更快?

-Edit2- 似乎偶尔我的 CPU 运行未排序和排序一样快。在其他机器上,它们的速度始终相同。我想我没有正确地进行基准测试,或者幕后发生了微妙的事情

- 编辑 - 下面的 ASM 代码。生成的代码在主循环中是相同的。有人可以确认它是更快还是相同?我正在使用 clang 10 并且我在 ryzen 3600 上。根据编译器资源管理器,没有分支,添加使用 SIMD 指令,该指令根据掩码添加 A 或 B。掩码来自 >= 128 并且 B 是 0 的向量。所以不,我所看到的没有隐藏的分支。

我认为这个非常受欢迎的问题很愚蠢,并在 clang 中尝试过为什么处理排序数组比处理未排序数组更快?

使用 g++ -O2 需要 2 秒,clang 需要 0.32。我尝试使它像下面这样无分支,发现即使它是无分支排序仍然使它更快。这是怎么回事?!(似乎 O2 对代码进行了矢量化,所以我没有尝试做更多)

#include <algorithm>
#include <ctime>
#include <stdio.h>

int main()
{
    // Generate data
    const unsigned arraySize = 32768;
    int data[arraySize];

    for (unsigned c = 0; c < arraySize; ++c)
        data[c] = std::rand() % 256;

    // !!! With …
Run Code Online (Sandbox Code Playgroud)

c++

6
推荐指数
1
解决办法
102
查看次数

如何检查两个图像是否相同但压缩方式不同?

举个例子,如果我将图像上传到 imgur 两次,并在另一个网站上上传一次,则很可能所有 3 个图像都有不同的校验和。jpeg 是有损的,所以我不能简单地检查像素是否匹配。

如何检查同一张图片是否有不同的编码?我不想编写算法,我想通过 CLI 使用库或离线应用程序

附加信息:如果裁剪方式不同,我更喜欢将其视为不同的图片,但对于我的用例而言,这并不重要(如果我想要的话,我可以简单地检查宽度和高度?)

image

5
推荐指数
1
解决办法
1209
查看次数

如何获取内部值以用作 gdb 漂亮打印的数组?

我为 InnerStruct 编写了一个漂亮的打印机,它将数组显示为 2 个元素和正确的值。我还为TestStruct2开了个玩笑,但是我不知道如何使TestStruct包含与InnerStruct相同的内容。我不知道如何从 gdb/python 访问 array.nestedVariables。我如何编写这个以便 TestStruct 给出与 InnerStruct 相同的结果?

来源

struct InnerStruct
{
    int buffer[100];
    int len;
};
struct TestStruct
{
    InnerStruct array;
};
struct TestStruct2
{
    InnerStruct array;
};

int main() {
    TestStruct s;
    s.array.buffer[0] = 5;
    s.array.buffer[1] = 8;
    s.array.len=2;
    TestStruct2 s2;
    s2.array.buffer[0] = 5;
    s2.array.buffer[1] = 8;
    s2.array.len=2;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

.gdbinit

python

pp = gdb.printing.RegexpCollectionPrettyPrinter("pp")

class InnerStructPrinter:
    "Print a InnerStruct"

    class _iterator:
        def __init__ (self, start, finish):
            self.item = start
            self.finish = finish …
Run Code Online (Sandbox Code Playgroud)

python gdb pretty-print

5
推荐指数
1
解决办法
212
查看次数

除了二进制文件中的代码之外,如何在没有任何内容的情况下编译 C?

我正在查看有关 hello world 二进制大小的页面,我想知道如果我没有 lib c 我可以获得多小的二进制文件。我从一些非常简单的事情开始(代码如下)。正如你所看到的,我运气不佳,5 条指令仍然是 13K 的二进制文件。我究竟做错了什么?

$ cat nolib.c 
void _start() {
    asm("mov $60,%rax; mov $1,%rdi; syscall");
}

$ gcc -nostdlib nolib.c
$ strip a.out
$ ls -lh
-rwxr-xr-x 1 eric eric 13K Nov 21 18:03 a.out
Run Code Online (Sandbox Code Playgroud)

c assembly gcc x86-64

5
推荐指数
1
解决办法
929
查看次数

是否有相当于 _aligned_realloc 的 linux

_aligned_realloc的 linux 等价物吗?

我想使用 realloc 所以我不必每次调整数据时都对数据进行 memcpy。我被 mmap 卡住了吗?我只使用了一次 mmap 是否有推荐的方法来实现将调整几次大小的内存?我假设我不能将 mmap 与aligned_alloc 混合使用,并且我必须在第一次调整大小时执行memcpy?(或始终使用 mmap)

下面的 realloc 并不总是对齐。我在(64位)linux下使用gcc和clang进行了测试

#include<cstdlib>
#include<cstdio>
#define ALIGNSIZE 64
int main()
{
    for(int i = 0; i<10; i++)
    {
        void *p = aligned_alloc(ALIGNSIZE, 4096);
        void *p2 = realloc(p, 4096+2048); //This doesn't always align
        //void *p3 = aligned_alloc(ALIGNSIZE, 4096/24); //Doesn't need this line to make it unaligned. 

        if (((long)p & (ALIGNSIZE-1)) != 0 || ((long)p2 & (ALIGNSIZE-1)) != 0)
            printf("%d %d %d\n", i, ((long)p & …
Run Code Online (Sandbox Code Playgroud)

c c++ linux

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

如何在 constexpr 中 strlen ?

我正在使用 clang++ 13.0.1
下面的代码可以工作,但显然很难看。我该如何写一个strlen?-编辑- 受到答案的启发,似乎我可以自己实现 strlen

#include <cstdio>
constexpr int test(const char*sz) {
    if (sz[0] == 0)
        return 0;
    if (sz[1] == 0)
        return 1;
    if (sz[2] == 0)
        return 2;
    return -1;
    //return strlen(sz);
}
constinit int c = test("Hi");

int main() {
    printf("C %d\n", c);
}
Run Code Online (Sandbox Code Playgroud)

c++ clang c++20

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

如何计算 mac M1 和 x86-64 上的前导零?

最初我尝试了 lzcnt 但似乎在 Mac 上不起作用。我正在与使用 Apple M1 CPU(ARM64v8.4)的人一起工作

在这个列出ARM 8的arm文档中,clz支持使用0

CLZ Xd、Xm
计数前导零(64 位):将 Xd 设置为 Xm 最高有效端的二进制零的数量。结果将在 0 到 64 范围内(含 0 和 64)。

我们最初支持的CPU是x86-64,它有_lzcnt_u64

如果值为 0,两条指令似乎都会返回 64。具体来说,ARM 上的“0 到 64包含在内”,英特尔网站也建议这样做(并由我的代码确认)

然而 GCC 说如下

内置函数:int __builtin_clzll (unsigned long long)

与 __builtin_clz 类似,但参数类型为 unsigned long long。

我可以安全地使用 0 还是这个内置函数使用不同的指令?我尝试了 clang,消毒剂停止了程序,并告诉我这是一个令我惊讶的问题。

如果我像这两条指令一样传入 0,那么当我想获得 64 时,我应该如何获得前导零计数

c++ bit-manipulation x86-64 arm64 apple-m1

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

用相同的 args 声明两个构造函数的最常用方式是什么?

举个例子,假设我有一个名为File. 现在文件可以以二进制或文本形式打开。我的构造函数目前是File(const char*filename). 让我们假设 open 的实现是完全不同的二进制和文本。我到底要怎么构造这个?

我考虑过使用静态函数,但我不想返回指针。我可以传入一个指针,但我宁愿不允许在没有实际初始化的情况下构造一个类。

我正在考虑在构造函数中使用 enum 或 bool ,但对我来说感觉“错误”(以及我可能这样做的方式)。我可以为二进制和文本使用不同的类名,并且两者都继承基本实现(或其他实现),即使唯一的区别是构造函数。

在 C++ 中这样做最惯用的方法是什么?

c++ constructor class

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

如何通过操作码或反汇编查找使用哪种形式的指令?

https://uops.info/和 Agner Fog 的指令表,甚至英特尔自己的手册这样的网站,都列出了相同指令的各种形式。例如add m, r(在 Agner 的表格中)或add (m64, r64)在 uops.info 上,或ADD r/m64, r64在英特尔的手册中(https://www.felixcloutier.com/x86/add)。


这是我在 Godbolt 上运行的一个简单示例

__thread int a;
void Test() {
    a+=5;
}
Run Code Online (Sandbox Code Playgroud)

添加是add DWORD PTR fs:0xfffffffffffffffc,0x5。它以操作码开头64 83 04 25

有几种方法可以编写我的真实代码,但我想查找这可能需要多少个周期以及其他信息。我怎么找到这个指令的参考?我尝试在https://uops.info/table.html 中输入“add”并检查我的架构。但我不知道哪个条目是正在使用的指令。

现在在这种特定情况下,我猜测操作码是Add m64, r64但我不知道fs:在地址之前使用是否有任何惩罚,或者是否有办法查看操作码,以便我可以确认我正在查看正确的参考

assembly x86-64 machine-code disassembly micro-architecture

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

告诉编译器不要在我的 __thread 变量上执行析构函数

我特别希望我的变量之一没有构造函数和析构函数。它的定义是这样的

struct Dummy { ~Dummy() { assert(0); } };
__thread Dummy dumb;
Run Code Online (Sandbox Code Playgroud)

真正的代码是零初始化的,并从线程本地内存池中获取内存。该池在 main 末尾被销毁,因此该析构函数尝试访问已释放的内存池。

我可以解决这个问题,但我想以一种干净的方式做到这一点。1)我可以告诉编译器在所有线程本地(或全局)变量之后释放我的池吗?或者是否在所有线程本地函数之前对其进行初始化,以便在适当的时间进行清理?或者更好的是 2) 根本不执行清理?我本可以发誓__thread不允许构造函数/析构函数,所以我很惊讶这甚至运行了。

堆栈跟踪显示__run_exit_handlers是调用析构函数的函数。它的父母是exit__libc_start_main并且start。这在 clang 和 gcc 上都会发生

c++ gcc clang

0
推荐指数
1
解决办法
311
查看次数

如何在 Rust 中使用序列号?

我正在寻找类似的东西(下面是C)

void MyFunction() {
    //Do work
    static int serial;
    ++serial;
    printf("Function run #%d\n", serial);
    //Do more work
}
Run Code Online (Sandbox Code Playgroud)

rust

0
推荐指数
1
解决办法
247
查看次数