我正在尝试编写一个非常便宜的C ++代码片段,以便在短的空终止字符串上执行以下操作。
输入是"ABC"
之类的字符串。它以null结尾,最大长度为4(或null终结符为5)。
输出转到char[4]
,它不是空终止的,应该在右边填充空格。所以在这种情况下,它将是{'A','B','C',' '}
可以假设输入字符串正确地以空值终止,因此无需读取输入的第二个字以确保输入字符串。它可以是4个字节。
所以围绕它的代码看起来像这样:
char* input = "AB";
char output[4];
// code snippet goes here
// afterward output will be populated with {'A','B',' ',' '}
这样做有多便宜? 如果重要:我正在使用:
Linux 2.6.32-358.11.1.el6.x86_64 #1 SMP x86_64 x86_64 x86_64 GNU/Linux
最后,输入是字对齐的。
答案 0 :(得分:3)
这样的事情怎么样:
typedef unsigned int word;
int spacePad(word input) {
static const word spaces = 0x20202020;
word mask =
!input ? 0 :
!(input & 0x00ffffff) ? 0xff:
!(input & 0x0000ffff) ? 0xffff :
!(input & 0x0000ff) ? 0xffffff :
0xffffffff;
// or without branches
word branchless_mask =
1u << (8 * (
bool(input & 0xff000000) +
bool(input & 0x00ff0000) +
bool(input & 0x0000ff00) +
bool(input & 0x000000ff)
));
return (spaces & mask) | (input & ~mask);
}
如果我没有搞砸,spacePad(0xaabb0000)
是0xaabb2020
。
除了计算和掩码之外,你可以使用SSE内在函数,这可能会更快,因为你在几条指令中得到了掩码,然后掩码移动会完成剩下的工作,但编译器可能会移动你的变量从SSE到标准寄存器,这可能超过轻微的增益。这完全取决于您需要处理多少数据,如何将其打包在内存中等等。
如果输入char*
而不是int
,则通常需要附加代码,因为强制转换可以读入未分配的内存。但是既然你提到所有字符串都是字对齐的,那么强制转换是足够的,实际上即使有一些未分配的字节,它们与至少一个分配的字节在同一个字上。由于您只是阅读没有内存损坏的风险,并且在我所知的所有体系结构上,硬件内存保护的粒度大于单词。例如,在x86上,内存页面通常是4k对齐的。
现在这一切都很好看,但是:在选择解决方案之前,基准测试,这是了解哪种方法最适合你的唯一方法(当然除了写代码之类的温暖模糊感觉这个^^)
答案 1 :(得分:1)
如果速度是你的问题 - 请使用蛮力。
这不会在其范围之外访问input
,也不会销毁它。
const char* input = TBD();
char output[4] = {' '};
if (input[0]) {
output[0] = input[0];
if (input[1]) {
output[1] = input[1];
if (input[2]) {
output[2] = input[2];
if (input[3]) {
output[3] = input[3];
}
}
}
}
答案 2 :(得分:1)
char* input = "AB";
char output[4];
input += (output[0] = *input ? *input : ' ') != ' ';
input += (output[1] = *input ? *input : ' ') != ' ';
input += (output[2] = *input ? *input : ' ') != ' ';
output[3] = *input ? *input : ' ';
请注意,这会破坏原始input
指针,因此如果需要保留它,请复制该指针。
答案 3 :(得分:1)
对于像这样的短字符串,我认为你不能比琐碎的实现做得更好:
char buffer[4];
const char * input = "AB";
const char * in = input;
char * out = buffer;
char * end = buffer + sizeof buffer;
while (out < end)
{
*out = *in != 0 ? *in++ : ' ';
out++;
}
答案 4 :(得分:0)
如果您的输入为空终止,则简单strcpy
就足够了。 memcpy更快,但会复制null char后找到的垃圾。
答案 5 :(得分:0)
您正在寻找memcpy
:
char* input = "AB\0\0";
char output[4];
memcpy(output, input, 4);
如果您的输入是可变的,则需要先计算尺寸:
char* input = "AB";
std::size_t len = strlen(input);
char output[4] = {' ', ' ', ' ', ' '};
memcpy(output, input, std::min(4, len));