【问题标题】:memcpy inverting data, C languagememcpy 反相数据,C语言
【发布时间】:2018-10-12 19:43:41
【问题描述】:

我对此有疑问,我正在尝试使用memcpy()string[9] 复制到unsigned long long int 变量,这是代码:

unsigned char string[9] = "message";
string[8] = '\0';
unsigned long long int aux;

memcpy(&aux, string, 8);
printf("%llx\n", aux); // prints inverted data

/* 
 * expected: 6d65737361676565
 *  printed: 656567617373656d
 */

如何在不反转数据的情况下制作此副本?

【问题讨论】:

  • 这就是unsigned long long int 存储其数据的方式。你无法改变这一点。如果你想以不同的顺序存储它,你需要在复制之前重新排列数据,或者在复制之后移动位。
  • 你的机器是Little Endian。
  • 或者如果只是打印,使用%02hhx 打印字符串中的单个字符。
  • 在学习 C 之前,您应该了解每个系统都有一个整数的内部表示(字节序、填充字节、符号表示、陷阱等)。哎呀,unsigned long long int 可能是 4 个字节(其中 CHAR_BIT 是 16,char 是 16 位,因此字节也是如此,C 允许这样做)......在这里您正在将 8 复制到其中...您正在涉足未定义的行为,这可能意味着您可以使用一本书来指导您避免编写不可移植、不稳定且难以调试的代码。

标签: c memcpy string.h


【解决方案1】:

您的系统对整数使用 little endian 字节排序。这意味着最低有效字节首先出现。例如,一个 32 位整数会将 258 (0x00000102) 存储为 0x02 0x01 0x00 0x00。

与其将字符串复制为整数,不如遍历字符并以十六进制打印每个字符:

int i;
int len = strlen(string);
for (i=0; i<len; i++) {
    printf("%02x ", string[i]);
}
printf("\n");

由于stringunsigned char 的数组,并且您正在为实现DES 进行位操作,因此您根本不需要更改它。照着用就好。

【讨论】:

    【解决方案2】:

    看起来您刚刚偶然发现了 CPU 是如何存储整数值的。有两个相互竞争的思想流派被称为endian,小端和大端都在野外发现。

    如果您希望它们按字节顺序排列,整数类型将有问题,应避免使用。只需使用一个字节数组。

    有一些转换函数可以从一种字节序形式转换为另一种,但在正确转换之前,您需要知道您的架构使用什么排序。

    因此,如果您正在读取二进制值,则必须知道它的字节序格式才能正确地将其导入本机 int 类型。在编写二进制文件以避免猜测时,选择一致的字节序形式通常是一个好习惯,其中绝大多数互联网协议中使用的“网络字节顺序”方案是一个很好的默认值。然后,您可以根据需要使用htonlntohl 等函数来回转换。

    【讨论】:

      猜你喜欢
      • 2011-01-15
      • 1970-01-01
      • 2011-04-05
      • 1970-01-01
      • 2013-04-07
      • 2017-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多