使用指向文字的指针访问指针

Accessing pointer with pointer to a literal

我必须向数组写入一些文字,但我只有数组的地址,所以我首先创建一个本地数组,用文字填充它,然后将内容复制到目标数组。这是一个例子:

void example(char *array) {
    char temp[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };    
    memcpy(array, temp, sizeof(temp));
}

这工作得很好,但我正在寻找一种在一行而不是两行中执行相同操作的方法。有人知道怎么做吗?

这比你的代码可读性差,我会说,但如果你只是必须在一行中完成...

memcpy(array, "\x01\x02\x03\x04\x05\x06\x07\x08", sizeof("\x01\x02\x03\x04\x05\x06\x07\x08") - 1);

您可以使用复合文字:

memcpy(array, (char []) {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08},
       sizeof ((char []) {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}));

可以使用define来避免重复数组(如果必须修改数组元素,这样更容易出错):

#define ARRAY  ((char []) {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08})

memcpy(array, ARRAY, sizeof ARRAY); 

我写下这个答案是因为你评论说你想在一行中完成它以避免“访问许多指针”。但你不会。任何体面的编译器都会对此进行优化。使用 -O1 的 GCC 在 x86_64 上为您的示例生成此代码,未更改。它甚至不调用 memcpy:

example:
.LFB12:
    .cfi_startproc
    movb    , (%rdi)
    movb    , 1(%rdi)
    movb    , 2(%rdi)
    movb    , 3(%rdi)
    movb    , 4(%rdi)
    movb    , 5(%rdi)
    movb    , 6(%rdi)
    movb    , 7(%rdi)
    ret
    .cfi_endproc

解释一下:</code>、<code>等是你的文字元素,%rdi是包含example的第一个参数的寄存器,即你的指针名为 array.

只需使用两条可读行。

假设机器是 LSB

*(unsigned long long *)array = 0x0807060504030201;

P.S。好吧,别太认真了;-)

P.P.S。让我提出另一个反对在函数内部使用 char[](而不是 static char[])的论点。

虽然优化编译器可以有时排除烦人的堆栈变量,但这并不总是可能的。例如,考虑调用其他函数,例如 printf("%s", temp)。它看起来很无辜,但是,由于 printf 的第二个参数不是 const,编译器 必须 创建 堆栈上的整个数组 temp,然后将其传递给printf.

对于一些大数组,这可能真的很痛苦!

编写代码的规范方式是这样的:

void example(char *array) {
    static const char temp[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };    
    memcpy(array, temp, sizeof(temp));
}

这是非常可读的,也是最快的,因为局部常量不会在每次函数调用时分配到堆栈上。但是,当然,编译器无论如何都会优化它。

没有理由尝试进一步手动优化此代码。字符串文字会使代码更难阅读。复合文字将具有局部作用域,并且在理论上为每个函数调用分配在堆栈上,这在理论上会使代码变慢 - 实际上,编译器可能会优化复合文字,以便它不会在每个函数调用时都被压入堆栈函数调用。

如果多个函数需要使用同一个常量,则在文件范围内声明它,但保留它static const这样你就不会把全局命名空间弄得乱七八糟。