【问题标题】:How to convert the template from C++ to C如何将模板从 C++ 转换为 C
【发布时间】:2019-11-06 05:42:52
【问题描述】:

我正在尝试将一些 C++ 代码转换为 C,以便我的编译器无法使用 C++ 代码运行。我想将下面的模板创建为 C。此模板将十进制整数转换为十六进制,如果十六进制字符串的大小小于(sizeof(T)*2),则在 value 前面添加 0。数据类型T可以是unsigned charcharshortunsigned shortintunsigned intlong longunsigned long long

template< typename T > std::string hexify(T i)
{
    std::stringbuf buf;
    std::ostream os(&buf);
    os << std::setfill('0') << std::setw(sizeof(T) * 2)
       << std::hex << i;
    std::cout<<"sizeof(T) * 2 = "<<sizeof(T) * 2<<"   buf.str() = "<<buf.str()<<"   buf.str.c_str() = "<<buf.str().c_str()<<std::endl;
    return buf.str().c_str();
}

感谢您的游览帮助。

编辑1:我尝试使用声明

char * hexify (void data, size_t data_size)

但是当我用 int 值int_value 调用时:

char * result = hexify(int_value, sizeof(int)) 

它不起作用,因为:

非竞争类型(void 和 int)。

那么在这种情况下,我必须使用宏吗?我没有尝试过使用宏,因为它很复杂。

【问题讨论】:

  • 你试过什么?请向我们展示您的 C 代码。在 C 中也没有 template 这样的东西。
  • 将您的 C 代码转换为 C++ 不是更容易吗?
  • 您可以像 printf() 这样的标准 C 函数那样做。接受指定类型的格式字符串。否则,有几个函数,每个类型一个。
  • 您只需返回buf.str() - 无需来回转换。另外,std::ostringstream 是一个东西,你不需要手动复制它。
  • 我会分步进行。首先用你需要的重载替换模板(因为 c 没有模板)。然后以不同的方式命名重载(因为 c 没有重载)。然后将这些函数中的每一个翻译成 C。请注意,在 C 中也有一些事情可以在不诉诸 void* 的情况下完成。如果您需要char* foo(int);,那么我总是更喜欢void* foo(void*);

标签: c++ c templates hex decimal


【解决方案1】:

如果您降级为原始位和字节,则不需要模板。

如果性能很重要,最好手动推出转换例程,因为 C 和 C++ 中的字符串处理函数会带来很多缓慢的开销。稍微优化的版本看起来像这样:

char* hexify_data (char*restrict dst, const char*restrict src, size_t size)
{
  const char NIBBLE_LOOKUP[0xF+1] = "0123456789ABCDEF";
  char* d = dst;

  for(size_t i=0; i<size; i++)
  {
    size_t byte = size - i - 1; // assuming little endian
    *d = NIBBLE_LOOKUP[ (src[byte]&0xF0u)>>4 ];
    d++;
    *d = NIBBLE_LOOKUP[ (src[byte]&0x0Fu)>>0 ];
    d++;
  }
  *d = '\0';
  return dst;
}

这使用字符类型逐字节分解任何传递的类型。这很好,当专门使用字符类型时。它还使用调用方分配来获得最佳性能。 (也可以通过每个循环的额外检查使其与字节顺序无关。)

我们可以使用包装宏使调用更方便:

#define hexify(buf, var) hexify_data(buf, (char*)&var, sizeof(var))

完整示例:

#include <string.h>
#include <stdint.h>
#include <stdio.h>

#define hexify(buf, var) hexify_data(buf, (char*)&var, sizeof(var))

char* hexify_data (char*restrict dst, const char*restrict src, size_t size)
{
  const char NIBBLE_LOOKUP[0xF+1] = "0123456789ABCDEF";
  char* d = dst;

  for(size_t i=0; i<size; i++)
  {
    size_t byte = size - i - 1; // assuming little endian
    *d = NIBBLE_LOOKUP[ (src[byte]&0xF0u)>>4 ];
    d++;
    *d = NIBBLE_LOOKUP[ (src[byte]&0x0Fu)>>0 ];
    d++;
  }
  *d = '\0';
  return dst;
}


int main (void)
{
  char buf[50];

  int32_t i32a = 0xABCD;
  puts(hexify(buf, i32a));

  int32_t i32b = 0xAAAABBBB;
  puts(hexify(buf, i32b));

  char c = 5;
  puts(hexify(buf, c));

  uint8_t u8 = 100;
  puts(hexify(buf, u8));
}

输出:

0000ABCD
AAAABBBB
05
64

【讨论】:

    【解决方案2】:

    一个可选的解决方案是使用格式字符串,如printf

    请注意,您不能返回指向局部变量的指针,但您可以获取缓冲区作为参数,(这里没有边界检查)。

    char* hexify(char* result, const char* format, void* arg)
    {
        int size = 0;
        if(0 == strcmp(format,"%d") || 0 == strcmp(format,"%u"))
        {
            size=4;
            sprintf(result,"%08x",arg);
        }
        else if(0 == strcmp(format,"%hd") || 0 == strcmp(format,"%hu"))
        {
            size=2;
            sprintf(result,"%04x",arg);
        }
        else if(0 == strcmp(format,"%hhd")|| 0 == strcmp(format,"%hhu"))
        {
            size=1;
            sprintf(result,"%02x",arg);
        }
        else if(0 == strcmp(format,"%lld") || 0 == strcmp(format,"%llu") )
        {
            size=8;
            sprintf(result,"%016x",arg);
        }
        //printf("size=%d", size);
        return result;
    
    }
    
    int main()
    {
        char result[256];
        printf("%s", hexify(result,"%hhu", 1));
    
        return 0;
    }
    

    【讨论】:

    • 这是非常过时的程序设计。您应该将此格式字符串替换为编译时_Generic。此外,“尤达条件”0 == ... 在 1989 年左右过时了。1989 年及以后的编译器会针对条件内部的意外赋值发出警告。
    【解决方案3】:

    C 没有模板。一种解决方案是传递支持的最大宽度整数(uintmax_t,在下面的Value)和原始整数的大小(在Size)。一个例程可以使用大小来确定要打印的位数。另一个复杂因素是 C 不提供 C++ 的std::string 自动内存管理。在 C 中处理此问题的典型方法是让被调用函数分配一个缓冲区并将其返回给调用者,调用者负责在完成后释放它。

    下面的代码显示了一个执行此操作的hexify 函数,它还显示了一个Hexify 宏,它接受一个参数并将其大小和值都传递给hexify 函数。

    请注意,在 C 中,诸如 'A' 之类的字符常量的类型为 int,而不是 char,因此在提供所需大小时需要小心。下面的代码包含一个示例。

    #include <inttypes.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    
    char *hexify(size_t Size, uintmax_t Value)
    {
        //  Allocate space for "0x", 2*Size digits, and a null character.
        size_t BufferSize = 2 + 2*Size + 1;
        char *Buffer = malloc(BufferSize);
    
        //  Ensure a buffer was allocated.
        if (!Buffer)
        {
            fprintf(stderr,
                "Error, unable to allocate buffer of %zu bytes in %s.\n",
                BufferSize, __func__);
            exit(EXIT_FAILURE);
        }
    
        //  Format the value as "0x" followed by 2*Size hexadecimal digits.
        snprintf(Buffer, BufferSize, "0x%0*" PRIxMAX, (int) (2*Size), Value);
    
        return Buffer;
    }
    
    
    /*  Provide a macro that passes both the size and the value of its parameter
        to the hexify function.
    */
    #define Hexify(x)   (hexify(sizeof (x), (x)))
    
    
    int main(void)
    {
        char *Buffer;
    
        /*  Show two examples of using the hexify function with different integer
            types.  (The examples assume ASCII.)
        */
    
        char x = 'A';
        Buffer = hexify(sizeof x, x);
        printf("Character '%c' = %s.\n", x, Buffer);  // Prints "0x41".
        free(Buffer);
    
        int i = 123;
        Buffer = hexify(sizeof i, i);
        printf("Integer %d = %s.\n", i, Buffer);  // Prints "0x00007b".
        free(Buffer);
    
        /*  Show examples of using the Hexify macro, demonstrating that 'A' is an
            int value, not a char value, so it would need to be cast if a char is
            desired.
        */
        Buffer = Hexify('A');
        printf("Character '%c' = %s.\n", 'A', Buffer);  // Prints "0x00000041".
        free(Buffer);
    
        Buffer = Hexify((char) 'A');
        printf("Character '%c' = %s.\n", 'A', Buffer);  // Prints "0x41".
        free(Buffer);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-10
      • 1970-01-01
      • 2021-11-21
      • 2023-01-22
      • 1970-01-01
      相关资源
      最近更新 更多