使用指向文字的指针访问指针
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
这样你就不会把全局命名空间弄得乱七八糟。
我必须向数组写入一些文字,但我只有数组的地址,所以我首先创建一个本地数组,用文字填充它,然后将内容复制到目标数组。这是一个例子:
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
这样你就不会把全局命名空间弄得乱七八糟。