【问题标题】:C Programming: strtol() and Dealing with NUL BytesC 编程:strtol() 和处理 NUL 字节
【发布时间】:2012-06-15 19:23:50
【问题描述】:

假设我有一个地址和一个偏移量,例如:

   char* base_addr = "\x00\x00\x00\xb7";
   char* addr_offset = (user input);

我想将 base_addr 和 addr_offset 添加在一起。我是否必须编写自己的 strtol() 函数,该函数不会在 NUL 处终止,还是有其他方法可以成功添加这两个地址?

编辑:

忘了说这是Linux x86。

【问题讨论】:

  • 我不清楚您将用户输入添加到现有字符串的确切含义。但是,基本上,是的,编写你自己的函数。这应该是微不足道的。

标签: c char hex


【解决方案1】:

base_addr 实际上是一个 32 位整数值,恰好是使用字节常量硬编码的。您应该简单地将指针的类型转换为unsigned long,然后在用户输入的字符串上调用strtol(),并将两者相加。

以这种方式使用字符串对指针进行硬编码是很糟糕的。一方面,C 会在字符串的末尾添加一个 NUL 字节,所以现在你的 32 位值需要 5 个字节,加上填充字节,你最终可能会使用 8 个字节来存储指针,正好是需要的两倍.最好这样做:

char base_addr[] = {'\x00', '\x00', '\x00', '\xb7'};

最好直接说出你的意思,只要编译器允许你进行类型转换:

unsigned char *base_addr = (unsigned char *)0xb7000000;

我刚刚检查过,GCC 允许您在没有错误或警告的情况下执行上述操作。

编辑:哦,好吧,真正的问题是如何访问整数值内的字节。

你应该可以通过弄乱指针来做到这一点:

unsigned long base_adr = 0xb700000000;
unsigned char *p = (unsigned char *)&base_adr;

上述技巧适用于整数类型。另一种方法是使用 C 联合:

typedef union
{
    char bytes[4];
    unsigned long n;
    unsigned char *ptr;
} ADR_WINDOW;

ADR_WINDOW x;

x.n = 0xb700000000;
assert(x.bytes[3] == 0xb7); // on a little-endian computer
assert(x.bytes[0] == 0xb7); // on a big-endian computer

联合技巧适用于任何类型,并且是执行低俗技巧(例如查看浮点值内的位)的唯一可移植方法。

【讨论】:

  • 在将两者加在一起后,如何将 unsigned long 恢复为字符串(我需要它作为包含小端字节的字符串)?
  • 我不认为这是正确的。您可以将任何内容投射到char*。为什么整数和浮点数应该不同?使用这样的联合在技术上是未定义的行为。你应该更喜欢uintptr_t/uint32_t 而不是unsigned long
  • 关于uintptr_t 的优点。但根据我的经验,尝试访问浮点数中的位是让 GCC 抱怨“类型双关指针”的一种快速方法。我不确定您是否正确地认为联合技巧是未定义的行为;这是 C 最接近官方方法的东西,我发现它是完全可移植的,甚至是 DSP 芯片。当然,整数值中字节的顺序取决于系统的字节顺序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-18
  • 2012-10-04
  • 1970-01-01
  • 1970-01-01
  • 2013-03-04
  • 2014-12-22
  • 1970-01-01
相关资源
最近更新 更多