【问题标题】:How do you reverse a string in place in C or C++?如何在 C 或 C++ 中反转字符串?
【发布时间】:2010-09-16 22:13:43
【问题描述】:

如何在 C 或 C++ 中反转字符串而不需要单独的缓冲区来保存反转的字符串?

【问题讨论】:

    标签: c++ c string reverse


    【解决方案1】:
    #include <algorithm>
    std::reverse(str.begin(), str.end());
    

    这是 C++ 中最简单的方法。

    【讨论】:

    • 在 C++ 中,字符串由字符串类表示。他没有要求“字符星”或“字符括号”。保持优雅,C.
    • @fredsbend,所选答案的“可笑的长”版本处理了这个简单答案没有的情况 - UTF-8 输入。它显示了完全指定问题的重要性。除了问题是关于在 C 中也可以工作的代码。
    • 如果您使用可识别 UTF-8 的字符串类(或者可能是带有 std::basic_string 的 utf-8 字符类),此答案会处理这种情况。此外,问题是“C 或 C++”,而不是“C 和 C++”。仅 C++ 是“C 或 C++”。
    • 这将完全破坏 UTF-8 多字节字符串,并且在当今时代完全无法启动。
    【解决方案2】:

    阅读 Kernighan 和 Ritchie

    #include <string.h>
    
    void reverse(char s[])
    {
        int length = strlen(s) ;
        int c, i, j;
    
        for (i = 0, j = length - 1; i < j; i++, j--)
        {
            c = s[i];
            s[i] = s[j];
            s[j] = c;
        }
    }
    

    【讨论】:

    • 在我的 iphone 上测试过,这比使用原始指针地址慢了大约 15%
    • 变量“c”不应该是char而不是int吗?
    • 在此示例中需要注意的是,字符串s 必须以数组形式声明。换句话说,char s[] = "this is ok" 而不是char *s="cannot do this",因为后者会导致无法修改的字符串常量
    • 向“教父”道歉......“放下枪,带上 K&R”。作为一个 C 偏执者,我会使用指针,因为它们更简单、更直接地解决这个问题,但代码对于 C#、Java 等的可移植性较差。
    • @Eric 这不会在 O(log(n)) 时间内运行。如果您指的是代码执行的字符交换次数,它在 O(n) 中运行,对于字符串长度的 n,然后执行 n 次交换。如果您说的是执行的循环数量,那么它仍然是 O(n) - 尽管是 O(n/2),但是您放弃了 Big O 表示法中的常量。
    【解决方案3】:

    标准算法是使用指向开始/结束的指针,然后将它们向内移动,直到它们在中间相遇或交叉。随时交换。


    反转 ASCII 字符串,即以 0 结尾的数组,其中每个字符都适合 1 char。 (或其他非多字节字符集)。

    void strrev(char *head)
    {
      if (!head) return;
      char *tail = head;
      while(*tail) ++tail;    // find the 0 terminator, like head+strlen
      --tail;               // tail points to the last real char
                            // head still points to the first
      for( ; head < tail; ++head, --tail) {
          // walk pointers inwards until they meet or cross in the middle
          char h = *head, t = *tail;
          *head = t;           // swapping as we go
          *tail = h;
      }
    }
    

    // test program that reverses its args
    #include <stdio.h>
    
    int main(int argc, char **argv)
    {
      do {
        printf("%s ",  argv[argc-1]);
        strrev(argv[argc-1]);
        printf("%s\n", argv[argc-1]);
      } while(--argc);
    
      return 0;
    }
    

    相同的算法适用于已知长度的整数数组,只需使用tail = start + length - 1 而不是结束查找循环。

    (编者注:这个答案最初也为这个简单的版本使用了 XOR-swap。为了这个热门问题的未来读者的利益而修复。XOR-swap is highly not recommended; 难以阅读并使您的代码编译效率降低。您可以请参阅on the Godbolt compiler explorer 当使用 gcc -O3 为 x86-64 编译 xor-swap 时,asm 循环体要复杂得多。)


    好的,好的,让我们修复 UTF-8 字符...

    (这是异或交换的事情。注意你必须避免与 self 交换,因为如果 *p*q 是同一个位置,你会用 a ^a==0。异或交换取决于有两个不同的位置,将它们分别用作临时存储。)

    编者注:您可以使用 tmp 变量将 SWP 替换为安全的内联函数。

    #include <bits/types.h>
    #include <stdio.h>
    
    #define SWP(x,y) (x^=y, y^=x, x^=y)
    
    void strrev(char *p)
    {
      char *q = p;
      while(q && *q) ++q; /* find eos */
      for(--q; p < q; ++p, --q) SWP(*p, *q);
    }
    
    void strrev_utf8(char *p)
    {
      char *q = p;
      strrev(p); /* call base case */
    
      /* Ok, now fix bass-ackwards UTF chars. */
      while(q && *q) ++q; /* find eos */
      while(p < --q)
        switch( (*q & 0xF0) >> 4 ) {
        case 0xF: /* U+010000-U+10FFFF: four bytes. */
          SWP(*(q-0), *(q-3));
          SWP(*(q-1), *(q-2));
          q -= 3;
          break;
        case 0xE: /* U+000800-U+00FFFF: three bytes. */
          SWP(*(q-0), *(q-2));
          q -= 2;
          break;
        case 0xC: /* fall-through */
        case 0xD: /* U+000080-U+0007FF: two bytes. */
          SWP(*(q-0), *(q-1));
          q--;
          break;
        }
    }
    
    int main(int argc, char **argv)
    {
      do {
        printf("%s ",  argv[argc-1]);
        strrev_utf8(argv[argc-1]);
        printf("%s\n", argv[argc-1]);
      } while(--argc);
    
      return 0;
    }
    
    • 为什么,是的,如果输入中断,这将愉快地交换到该位置之外。
    • 在 UNICODE 中破坏时有用的链接:http://www.macchiato.com/unicode/chart/
    • 此外,UTF-8 over 0x10000 未经测试(因为我似乎没有任何字体,也没有耐心使用 hexeditor)

    例子:

    $ ./strrev Räksmörgås ░▒▓○◔◑◕●
    
    ░▒▓○◔◑◕● ●◕◑◔○▓▒░
    
    Räksmörgås sågrömskäR
    
    ./strrev verrts/.
    

    【讨论】:

    • 没有充分的理由在混淆代码竞争之外使用 XOR 交换。
    • 你认为“就地”意味着“没有额外的内存”,甚至不是 O(1) 临时内存? str 的栈空间和返回地址呢?
    • @Bill,这不是“就地”的常见定义。就地算法可能使用额外的内存。然而,这个额外的内存量不能依赖于输入——即它必须是恒定的。因此,使用额外存储交换值是完全就地的。
    • 在异或交换消失之前不会对此表示赞同。
    • XOR 交换比通过现代乱序处理器上的寄存器交换慢。
    【解决方案4】:

    非邪恶的 C,假设字符串是一个以 null 结尾的 char 数组的常见情况:

    #include <stddef.h>
    #include <string.h>
    
    /* PRE: str must be either NULL or a pointer to a 
     * (possibly empty) null-terminated string. */
    void strrev(char *str) {
      char temp, *end_ptr;
    
      /* If str is NULL or empty, do nothing */
      if( str == NULL || !(*str) )
        return;
    
      end_ptr = str + strlen(str) - 1;
    
      /* Swap the chars */
      while( end_ptr > str ) {
        temp = *str;
        *str = *end_ptr;
        *end_ptr = temp;
        str++;
        end_ptr--;
      }
    }
    

    【讨论】:

    • 而不是使用while循环来查找结束指针,你不能使用像end_ptr = str + strlen (str);这样的东西吗?我知道这实际上会做同样的事情,但我发现它更清楚。
    • 很公平。我试图(但失败了)避免@uvote 的答案中的一个错误。
    • 除了int temp 可能带来潜在 性能改进之外,这个解决方案看起来最好。 +1
    • @chux-ReinstateMonica 是的。真漂亮。不过,我个人会从 !(*str) 中删除 ()。
    • @PeterKühne 是或 strchr() 搜索 '\0'。我都想到了。不需要循环。
    【解决方案5】:

    已经有一段时间了,我不记得哪本书教过我这个算法,但我认为它非常巧妙且易于理解:

    char input[] = "moc.wolfrevokcats";
    
    int length = strlen(input);
    int last_pos = length-1;
    for(int i = 0; i < length/2; i++)
    {
        char tmp = input[i];
        input[i] = input[last_pos - i];
        input[last_pos - i] = tmp;
    }
    
    printf("%s\n", input);
    

    此算法的可视化,由slashdottir提供:

    【讨论】:

    • 这是一个有趣的变化是的。不过技术上应该是size_t
    【解决方案6】:

    请注意,std::reverse 的美妙之处在于它可以与 char * 字符串和 std::wstrings 以及 std::strings 一起使用

    void strrev(char *str)
    {
        if (str == NULL)
            return;
        std::reverse(str, str + strlen(str));
    }
    

    【讨论】:

      【解决方案7】:

      如果您正在寻找反转 NULL 终止的缓冲区,这里发布的大多数解决方案都可以。但是,正如 Tim Farley 已经指出的那样,这些算法只有在假设字符串在语义上是字节数组(即单字节字符串)是有效的情况下才有效,我认为这是一个错误的假设。

      以字符串“año”(西班牙语中的年份)为例。

      Unicode 码位是 0x61、0xf1、0x6f。

      考虑一些最常用的编码:

      Latin1 / iso-8859-1(单字节编码,1个字符为1个字节,反之亦然):

      原文:

      0x61, 0xf1, 0x6f, 0x00

      反向:

      0x6f, 0xf1, 0x61, 0x00

      结果还可以

      UTF-8:

      原文:

      0x61、0xc3、0xb1、0x6f、0x00

      反向:

      0x6f, 0xb1, 0xc3, 0x61, 0x00

      结果是乱码和非法的 UTF-8 序列

      UTF-16 大端:

      原文:

      0x00, 0x61, 0x00, 0xf1, 0x00, 0x6f, 0x00, 0x00

      第一个字节将被视为 NUL 终止符。不会发生逆转。

      UTF-16 小端:

      原文:

      0x61, 0x00, 0xf1, 0x00, 0x6f, 0x00, 0x00, 0x00

      第二个字节将被视为 NUL 终止符。结果将是 0x61, 0x00,一个包含 'a' 字符的字符串。

      【讨论】:

      • std::reverse 将适用于两字节 unicode 类型,只要您使用的是 wstring。
      • 我对 C++ 不是很熟悉,但我的猜测是任何处理字符串的受人尊敬的标准库函数都能够处理不同的编码,所以我同意你的看法。我所说的“这些算法”是指此处发布的临时反向函数。
      • 不幸的是,标准 C++ 中没有“处理字符串的可敬函数”这样的东西。
      • @Eclipse 如果它反转代理对,结果将不再正确。 Unicode 实际上不是固定宽度的字符集
      • 我喜欢这个答案的地方在于它显示了字节的实际顺序(尽管字节序可能是某种东西 - 啊,我看到你确实考虑过它)以及它是如何正确或不正确的。但我认为如果你合并一些代码来证明这一点,答案会得到改善。
      【解决方案8】:

      为了完整起见,应该指出的是,在各种平台上都有字符串的表示形式,其中每个字符的字节数因字符而异 .老派程序员会将其称为DBCS (Double Byte Character Set)。现代程序员更常在UTF-8(以及UTF-16 和其他人)中遇到这种情况。还有其他这样的编码。

      在任何这些可变宽度编码方案中,此处发布的简单算法(evilnon-evilotherwise)根本无法正常工作!事实上,它们甚至可能导致字符串变得难以辨认,甚至是该编码方案中的非法字符串。请参阅Juan Pablo Califano's answer 了解一些很好的示例。

      std::reverse() 在这种情况下可能仍然有效,只要您的平台对标准 C++ 库(特别是字符串迭代器)的实现正确考虑到这一点。

      【讨论】:

      • std::reverse 没有考虑到这一点。它反转 value_type 的。在 std::string 的情况下,它反转 char。不是字符。
      • 不如说我们这些老派程序员知道 DBCS,但也知道 UTF-8:因为我们都知道,当他们说 '多一行我会退出!' 我敢肯定有些程序员最终会退出,但坦率地说,编程对我来说真的是一种瘾;我从不编程中得到提款。这是一个很好的观点,你在这里添加。我不喜欢 C++(我真的很努力地喜欢它,即使写了很多,但至少可以说它在美学上对我来说仍然没有吸引力)所以我不能在那里发表评论,但无论如何你说得很好所以有一个 +1。
      【解决方案9】:

      另一种 C++ 方式(虽然我自己可能会使用 std::reverse() :) 因为更具表现力和更快)

      str = std::string(str.rbegin(), str.rend());
      

      C 方式(或多或少:)) 请注意交换的异或技巧, 编译器有时无法优化。

      In such case it is usually much slower.

      char* reverse(char* s)
      {
          char* beg = s, *end = s, tmp;
          while (*end) end++;
          while (end-- > beg)
          { 
              tmp  = *beg; 
              *beg++ = *end;  
              *end =  tmp;
          }
          return s;
      } // fixed: check history for details, as those are interesting ones
      

      【讨论】:

      • 如果字符串可能很长,我会使用strlen 来查找字符串的结尾。一个好的库实现将使用 SIMD 向量来比每次迭代更快地搜索 1 个字节。但是对于非常短的字符串,while (*++end); 将在库函数调用开始搜索之前完成。
      • @PeterCordes 好吧,同意,为了可读性,无论如何都应该使用 strlen。对于更长的字符串,无论如何您都应该始终将长度保持在变量中。在 SIMD 上的 strlen 通常与此免责声明一起作为示例给出,这不是现实生活中的应用程序,或者至少是 5 年前编写代码的时候。 ;)
      • 如果您希望它在真正的 CPU 上快速运行,您可以使用 SIMD shuffle 在 16B 块中执行相反的操作。 :P 例如在 x86 上,_mm_shuffle_epi8 (PSHUFB) 可以反转 16B 向量的顺序,给定正确的随机播放控制向量。经过一些仔细的优化,它可能会以接近 memcpy 的速度运行,尤其是使用 AVX2。
      • char* beg = s-1 具有未定义的行为(至少如果s 指向数组的第一个元素,这是最常见的情况)。如果s 是空字符串,while (*++end); 的行为未定义。
      • @pprzemek 好吧,即使s 指向数组的第一个元素,您也声称s-1 已定义行为,因此您应该能够在支持。
      【解决方案10】:
      #include <cstdio>
      #include <cstdlib>
      #include <string>
      
      void strrev(char *str)
      {
              if( str == NULL )
                      return;
      
              char *end_ptr = &str[strlen(str) - 1];
              char temp;
              while( end_ptr > str )
              {
                      temp = *str;
                      *str++ = *end_ptr;
                      *end_ptr-- = temp;
              }
      }
      
      int main(int argc, char *argv[])
      {
              char buffer[32];
      
              strcpy(buffer, "testing");
              strrev(buffer);
              printf("%s\n", buffer);
      
              strcpy(buffer, "a");
              strrev(buffer);
              printf("%s\n", buffer);
      
              strcpy(buffer, "abc");
              strrev(buffer);
              printf("%s\n", buffer);
      
              strcpy(buffer, "");
              strrev(buffer);
              printf("%s\n", buffer);
      
              strrev(NULL);
      
              return 0;
      }
      

      这段代码产生这个输出:

      gnitset
      a
      cba
      

      【讨论】:

      • @uvote,不要使用 strcpy。曾经。如果您必须使用 strcpy 之类的东西,请使用 strncpy。 strcpy 是危险的。顺便说一句,C 和 C++ 是两种不同的语言,具有不同的功能。我认为您使用的是仅在 C++ 中可用的头文件,所以您真的需要 C 中的答案吗?
      • strcpy 如果程序员可以跟踪他的数组的大小是完全安全的,许多人会认为 strncpy 不太安全,因为它不能保证结果字符串是空终止的。无论如何,这里 uvote 使用 strcpy 并没有错。
      • @Onorio Catenacci,如果您知道源字符串将适合目标缓冲区,那么 strcpy 并不危险,就像上面代码中给出的情况一样。此外,如果有剩余空间,strncpy 将零填充到 size 参数中指定的字符数,这可能是不希望的。
      • 任何不能正确使用 strcpy 的人都不应该使用 C 编程。
      • @Robert Gamble,我同意。但是,由于我不知道有什么方法可以阻止人们使用 C 编程,无论他们的能力如何,我通常建议不要这样做。
      【解决方案11】:

      如果您使用 GLib,它有两个功能,g_strreverse()g_utf8_strreverse()

      【讨论】:

        【解决方案12】:

        我喜欢 Evgeny 的 K&R 答案。但是,很高兴看到使用指针的版本。否则,基本上是一样的:

        #include <stdio.h>
        #include <string.h>
        #include <stdlib.h>
        
        char *reverse(char *str) {
            if( str == NULL || !(*str) ) return NULL;
            int i, j = strlen(str)-1;
            char *sallocd;
            sallocd = malloc(sizeof(char) * (j+1));
            for(i=0; j>=0; i++, j--) {
                *(sallocd+i) = *(str+j);
            }
            return sallocd;
        }
        
        int main(void) {
            char *s = "a man a plan a canal panama";
            char *sret = reverse(s);
            printf("%s\n", reverse(sret));
            free(sret);
            return 0;
        }
        

        【讨论】:

          【解决方案13】:

          在原地反转字符串的递归函数(没有额外的缓冲区,malloc)。

          简短、性感的代码。糟糕,糟糕的堆栈使用。

          #include <stdio.h>
          
          /* Store the each value and move to next char going down
           * the stack. Assign value to start ptr and increment 
           * when coming back up the stack (return).
           * Neat code, horrible stack usage.
           *
           * val - value of current pointer.
           * s - start pointer
           * n - next char pointer in string.
           */
          char *reverse_r(char val, char *s, char *n)
          {
              if (*n)
                  s = reverse_r(*n, s, n+1);
             *s = val;
             return s+1;
          }
          
          /*
           * expect the string to be passed as argv[1]
           */
          int main(int argc, char *argv[])
          {
              char *aString;
          
              if (argc < 2)
              {
                  printf("Usage: RSIP <string>\n");
                  return 0;
              }
          
              aString = argv[1];
              printf("String to reverse: %s\n", aString );
          
              reverse_r(*aString, aString, aString+1); 
              printf("Reversed String:   %s\n", aString );
          
              return 0;
          }
          

          【讨论】:

          • 这是一个非常有趣的解决方案,您应该添加一些跟踪,例如 printf("%*s > [%d] reverse_r('%c', %p=\"%s\", %p =\"%s\")\n", depth, " ", depth, val, s, (s ? s : "null"), n, (n ? n : "null"));在开头和
          • 将每个char 推入堆栈不算作“就地”。尤其是当您实际推动每个字符 4 * 8B 时(在 64 位机器上:3 个 args + 一个返回地址)。
          • 最初的问题是“如何在 C 或 C++ 中反转字符串而不需要单独的缓冲区来保存反转的字符串?” - 不需要“就地”交换。此外,这个解决方案从一开始就提到了糟糕的堆栈使用。我是否因为其他人的阅读理解能力差而被否决?
          • 我不会称其为“性感”,但我会说它具有示范性和指导性。如果递归使用得当,它可能非常有价值。然而,应该指出的是——我最后知道——C 甚至不需要堆栈本身;但是它确实递归。无论哪种方式,它都是递归的一个例子,如果使用得当,它会非常有用和有价值。不过,我认为我从未见过它用于反转字符串。
          【解决方案14】:

          如果您使用 ATL/MFC CString,只需调用 CString::MakeReverse()

          【讨论】:

            【解决方案15】:

            还有一个:

            #include <stdio.h>
            #include <strings.h>
            
            int main(int argc, char **argv) {
            
              char *reverse = argv[argc-1];
              char *left = reverse;
              int length = strlen(reverse);
              char *right = reverse+length-1;
              char temp;
            
              while(right-left>=1){
            
                temp=*left;
                *left=*right;
                *right=temp;
                ++left;
                --right;
            
              }
            
              printf("%s\n", reverse);
            
            }
            

            【讨论】:

            • 这演示了指针运算,很像我的答案,但将它与交换结合起来。我相信这个答案实际上增加了很多。在添加十亿个库作为依赖项之前,您应该能够理解这种类型的代码,只是为了得到一些简单的文本框(我在使用的现代应用程序中经常看到的东西)
            【解决方案16】:
            #include <stdio.h>
            #include <stdlib.h>
            #include <string.h>
            #include <stdbool.h>
            
            unsigned char * utf8_reverse(const unsigned char *, int);
            void assert_true(bool);
            
            int main(void)
            {
                unsigned char str[] = "mañana mañana";
                unsigned char *ret = utf8_reverse(str,  strlen((const char *) str) + 1);
            
                printf("%s\n", ret);
                assert_true(0 == strncmp((const char *) ret, "anãnam anañam", strlen("anãnam anañam") + 1));
            
                free(ret);
            
                return EXIT_SUCCESS;
            }
            
            unsigned char * utf8_reverse(const unsigned char *str, int size)
            {
                unsigned char *ret = calloc(size, sizeof(unsigned char*));
                int ret_size = 0;
                int pos = size - 2;
                int char_size = 0;
            
                if (str ==  NULL) {
                    fprintf(stderr, "failed to allocate memory.\n");
                    exit(EXIT_FAILURE);
                }
            
                while (pos > -1) {
            
                    if (str[pos] < 0x80) {
                        char_size = 1;
                    } else if (pos > 0 && str[pos - 1] > 0xC1 && str[pos - 1] < 0xE0) {
                        char_size = 2;
                    } else if (pos > 1 && str[pos - 2] > 0xDF && str[pos - 2] < 0xF0) {
                        char_size = 3;
                    } else if (pos > 2 && str[pos - 3] > 0xEF && str[pos - 3] < 0xF5) {
                        char_size = 4;
                    } else {
                        char_size = 1;
                    }
            
                    pos -= char_size;
                    memcpy(ret + ret_size, str + pos + 1, char_size);
                    ret_size += char_size;
                }    
            
                ret[ret_size] = '\0';
            
                return ret;
            }
            
            void assert_true(bool boolean)
            {
                puts(boolean == true ? "true" : "false");
            }
            

            【讨论】:

              【解决方案17】:

              C++ 多字节 UTF-8 逆向器

              我的想法是你永远不能只交换结尾,你必须总是从头到尾移动,遍历字符串并寻找“这个字符需要多少字节?”我从原始结束位置开始附加字符,并从字符串的前面删除字符。

              void StringReverser(std::string *original)
              {
                int eos = original->length() - 1;
                while (eos > 0) {
                  char c = (*original)[0];
                  int characterBytes;
                  switch( (c & 0xF0) >> 4 ) {
                  case 0xC:
                  case 0xD: /* U+000080-U+0007FF: two bytes. */
                    characterBytes = 2;
                    break;
                  case 0xE: /* U+000800-U+00FFFF: three bytes. */
                    characterBytes = 3;
                    break;
                  case 0xF: /* U+010000-U+10FFFF: four bytes. */
                    characterBytes = 4;
                    break;
                  default:
                    characterBytes = 1;
                    break;
                  }
              
                  for (int i = 0; i < characterBytes; i++) {
                    original->insert(eos+i, 1, (*original)[i]);
                  }
                  original->erase(0, characterBytes);
                  eos -= characterBytes;
                }
              }
              

              【讨论】:

                【解决方案18】:
                void reverseString(vector<char>& s) {
                        int l = s.size();
                        char ch ;
                        int i = 0 ;
                        int j = l-1;
                        while(i < j){
                                s[i] = s[i]^s[j];
                                s[j] = s[i]^s[j];
                                s[i] = s[i]^s[j];
                                i++;
                                j--;
                        }
                        for(char c : s)
                                cout <<c ;
                        cout<< endl;
                }
                

                【讨论】:

                  【解决方案19】:

                  在 C++ 中,可以在函数中完成相反的操作:

                  #include <algorithm>
                  #include <string>
                  
                  void backwards(vector<string> &inputs_ref) {
                      for (auto i = inputs_ref.begin(); i != inputs_ref.end(); ++i) {
                          reverse(i->begin(), i->end());
                      }
                  }
                  

                  【讨论】:

                    【解决方案20】:

                    如果不需要存储,可以这样减少时间:

                    void showReverse(char s[], int length)
                    {
                        printf("Reversed String without storing is ");
                        //could use another variable to test for length, keeping length whole.
                        //assumes contiguous memory
                        for (; length > 0; length--)
                        {
                            printf("%c", *(s+ length-1) );
                        }
                        printf("\n");
                    }
                    

                    【讨论】:

                    • 我似乎是唯一没有缓冲区或临时变量的答案。我使用字符串的长度,但是这样做的其他人为头部(相对于尾部)添加了另一个字符串。我假设标准反向函数通过交换或其他方式存储变量。因此,我的印象是,假设指针数学和 UTF 类型对齐,这可能是唯一真正回答问题的答案。可以取出添加的 printf(),我只是为了让结果看起来更好。我写这个是为了速度。没有额外的分配或变量。可能是显示反向 str() 的最快算法
                    猜你喜欢
                    • 2010-10-21
                    • 2015-05-24
                    • 2013-07-11
                    • 2020-02-07
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多