快速填充strcpy单个单词

时间:2013-11-26 17:58:45

标签: c++ c word memcpy strcpy

我正在尝试编写一个非常便宜的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

最后,输入是字对齐的。

6 个答案:

答案 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));