【问题标题】:How to put the characters of a 16 byte char array into a 16 byte u_int32_t array?如何将 16 字节 char 数组的字符放入 16 字节 uint32_t 数组中?
【发布时间】:2020-03-07 18:17:44
【问题描述】:

假设我有一个 char 指针,我想把它放入一个 16 个字符的 char 数组中(即使 char 指针的 strlen() 大于那个,然后截断),很简单,我只是这样做:

char* pointer = <insert whatever here>;
unsigned char myArray[16];
memcpy(myArray, pointer, 16);

现在,我想将 char 数组放入一个 16 字节的 u_int32_t 数组中。
这是我正在尝试的:

u_int32_t newArray[4];
memcpy(newArray, myArray, 16);

这似乎并没有按照我想要的方式复制字节。我在这里错过了一些基本的 C 步骤吗?
我应该以不同的方式将 char 数组放入 u_int32_t 数组中吗?

【问题讨论】:

  • memcpy 不关心您正在复制的内容的类型。您需要一个循环,复制每个元素,并可能在分配之前将其转换或转换为适当的类型。
  • 请描述使您认为“这似乎不是按照我想要的方式复制字节的观察结果。”
  • 您可能在这里遇到字节序问题。
  • @TarekDakhran 可能,让我们等待 OP 的一些细节。
  • 约翰,关于是否存在诸如“问题noobishness”之类的完全切线的哲学话题:我们不能容忍它!我们消灭它Muhahahaha。不是。我希望你看到我们通过帮助你改进你的问题来防止它。还不错,也有点意思。只需提供更多信息和细节。然后它可能会提出重复的建议。这意味着它一点也不差,只是已经类似地问过了。所以,不要害怕。只需与我们合作。我们想提供帮助。如果我们认为有必要,我们只会解释规则。

标签: c


【解决方案1】:

指针算术是您可能需要了解的内容。当您声明一个 uint32_t 类型的数组时,编译器会自动在后台执行魔术以执行 4 个字节的增量。参考下面的例子

 #include <stdio.h>
 #include<string.h>
 #include<stdint.h>
 char* pointer = "HelloWorld!Hell!";
 uint32_t arr[4];
 unsigned char myArray[16];
 int main(void) {
     memcpy(arr, pointer, (size_t)16);
     //Generates warning but still works, because format is an indication to printf
     // how to deal with this array.
     printf("%s\n", arr); 
     char *arr1 = (char *)arr;

     for(int i = 0 ; i < 16; i++)
     {
         printf("arr[%d]=%c\n", i, arr1[i]);
     }
 }

【讨论】:

  • "//生成警告但仍然有效" --> 是的 未定义行为 (UB) 有时“有效”,但会导致代码不可靠。不是一个好的解决方案。
  • 这里的 UB 是什么?
  • printf("%s\n", arr); 需要一个字符指针。 arr,作为函数参数,是一个uint32t *。这些指针未指定为相同大小或相同形式。 “如果转换规范无效,则行为未定义” C17dr § 7.21.6.1 9. 可以使用 printf("%s\n", *char*) arr);。有关更多详细信息,建议以问题的形式发布。
【解决方案2】:

好吧,memcpy 似乎有效(可能是一些字节序问题,正如 cmets 中所指出的那样),但如果您愿意,您也可以使用循环。

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

int main()
{
    char arr[16] = {1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12, 13, -14, 15, -16};
    uint32_t newArray[4];
    uint32_t otherArray[4];

    memcpy(newArray, arr, 16);

    for (int i = 0; i < 4; i++)
      printf("%d %d %d %d ", (char)(newArray[i] & 0xFF),
                             (char)((newArray[i] & 0xFF00) >> 8),
                             (char)((newArray[i] & 0xFF0000) >> 16),
                             (char)((newArray[i] & 0xFF000000) >> 24));

    putchar('\n');

    // Copy via loop using bitwise OR and shifting
    for (int i = 0; i < 16; i += 4)
      otherArray[i / 4] = (((uint32_t)arr[i + 3]) << 24) & 0xFF000000 |
                          (((uint32_t)arr[i + 2]) << 16) & 0xFF0000   |
                          (((uint32_t)arr[i + 1]) << 8)  & 0xFF00     |
                          (uint32_t)arr[i];

    for (int i = 0; i < 4; i++)
      printf("%d %d %d %d ", (char)(otherArray[i] & 0xFF),
                             (char)((otherArray[i] & 0xFF00) >> 8),
                             (char)((otherArray[i] & 0xFF0000) >> 16),
                             (char)((otherArray[i] & 0xFF000000) >> 24));

    return 0;
}

输出

1 -2 3 -4 5 -6 7 -8 9 -10 11 -12 13 -14 15 -16 
1 -2 3 -4 5 -6 7 -8 9 -10 11 -12 13 -14 15 -16 

【讨论】:

  • @chux-ReinstateMonica 2) 是的,我承认我对此很懒惰,已更正它 1) 你确定吗?更改了代码,它似乎可以工作(仅打印需要调整)。还是我在监督什么?
  • 哦,你说得对,我严重忽略了...修复它。现在我猜它应该真的可以工作了。
  • @chux-ReinstateMonica 哦,你是对的,因为隐式 int 提升...希望我修复它。
  • 足够好了。另一种方式:((uint32_t)(unsigned char)arr[i + 3]) &lt;&lt; 24).
猜你喜欢
  • 1970-01-01
  • 2018-07-30
  • 1970-01-01
  • 1970-01-01
  • 2020-07-17
  • 2021-11-30
  • 2014-06-01
  • 2019-03-23
  • 1970-01-01
相关资源
最近更新 更多