C 使用指向文本的指针访问指针
我必须向数组写入一些文字,但我只有数组的地址,所以我首先创建一个本地数组,用文字填充它,然后将内容复制到目标数组。以下是一个例子:C 使用指向文本的指针访问指针,c,arrays,literals,C,Arrays,Literals,我必须向数组写入一些文字,但我只有数组的地址,所以我首先创建一个本地数组,用文字填充它,然后将内容复制到目标数组。以下是一个例子: void example(char *array) { char temp[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; memcpy(array, temp, sizeof(temp)); } 这很好,但我正在寻找一种方法,在一行而不是两行内实现同样的效果。有人知道如何做到
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来避免重复数组(如果必须修改数组元素,则更容易出错):
我写下这个答案是因为你评论说为了避免“访问多个指针”,你想在一行中完成它。但你不会。任何合适的编译器都会对此进行优化。带有
-O1
的GCC在x86_64
上生成此代码,对于您的示例,未作更改。它甚至不调用memcpy
:
example:
.LFB12:
.cfi_startproc
movb $1, (%rdi)
movb $2, 1(%rdi)
movb $3, 2(%rdi)
movb $4, 3(%rdi)
movb $5, 4(%rdi)
movb $6, 5(%rdi)
movb $7, 6(%rdi)
movb $8, 7(%rdi)
ret
.cfi_endproc
解释:$1
,$2
等是文本的元素,%rdi
是包含示例的第一个参数的寄存器,即您命名的数组
只需使用这两条可读的行。假设机器是LSB
*(无符号长*)数组=0x0807060504030201代码>
另外,好吧,不要太严肃;-)
另外,让我加入另一个反对在函数中使用char[]
(而不是static char[]
)的论点
虽然优化编译器有时可以排除恼人的堆栈变量,但这并不总是可能的。例如,考虑调用其他函数,例如,代码> PROTF(“%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
,这样就不会使全局名称空间过于混乱。在一行而不是两行上执行此操作没有任何好处。。。在可读性和性能方面,您的代码已经非常理想了;memcpy(数组、临时、大小f(临时))代码>只需删除换行符;)隐马尔可夫模型,。。嗯,我必须访问许多指针,但是如果没有其他解决方案,我每次都会这样做。使用static char temp[]
?@Lui显式分配指针与使用字符串文本或复合文本隐式分配指针没有区别。您复制的数据必须存储在内存中。没有数据可以在稀薄的空气中存储。驻留在内存中的所有数据都有一个地址。地址==指针。因此,保持代码原样,不要尝试任何预成熟优化。为什么要在sizeof(…)-1
中-1
?@CoolGuy删除“\0”,因为字符串是0-termianted的,我们不想在末尾复制零。;-)@福斯布鲁,哦,是的。我忘了,“…”
已经被NUL终止。这实际上只是对原始代码的混淆。我想你错过了一个“{”,但我不能编辑你的帖子。:-(这对我来说很好,但我得到了一个“临时数组的地址”-错误。请注意,这不会在所有环境中编译。不过,GCC看起来不错,这可能涵盖了大多数人的情况。为了澄清我的最后一条评论,它看起来是有效的C99,我认为这是我们在工作中编译的,但它不会为我编译。只要你有一个符合标准的编译器,你就有可能bly fine:)它不“好看”。它将以前的局部变量暴露到全局命名空间中。这很难看。至少使用文件范围静态常量
,而不是宏。或者更好的是,让代码保持原样,但使局部变量静态常量
(当然,除非线程安全是个问题)。作为旁注,char
、static char
和static const char
之间有区别。下面是要玩的代码-请看temp
是如何变化的。@user4419802不需要优化就可以了。char
=堆栈,static char
=.data,static const char
=.data。但是,如果您在上编译所有优化(例如gcc-o3),您会注意到,无论使用哪种形式,您都会得到完全相同的地址。这就是为什么,例如,原始代码或复合文本不会增加任何开销,正如我在回答中所提到的。当启用优化时,除了编译器本身之外,没有人可以预测输出代码。但是,给编译器一些提示仍然是一个好主意。这这就是为什么我认为上面的代码是规范的,它应该给出与启用完全优化的代码相同的机器代码。(虽然编译器可能认为在相邻内存中分配“array”和“temp”并进行优化更聪明。)
void example(char *array) {
static const char temp[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
memcpy(array, temp, sizeof(temp));
}