C函数替换参数特定索引中的字节

C function replace a byte in a specific index of a parameter

所以我使用以下代码:

unsigned long replaceByte(unsigned long original,unsigned char newByte,int indexToReplace)
{
    int shift = 8 * indexToReplace;
        unsigned long value = newByte << shift;
        unsigned long mask = 0xff << shift;

        return (~mask & original) | value;
}

我用|w|给定了一个词字节。

例如:

replaceByte(unsigned long original, unsigned char newByte, int indexToReplace)
correct answer:
replaceByte(0x12345678CDEF3456, 0xAB, 2) --> 0x1234AB78CDEF3456
                       (my code's output is: 0x12345678CDAB3456)
correct answer:
replaceByte(0x12345678CDEF3456, 0xAB, 0) --> 0xAB345678CDEF3456
                       (my code's output is: 0x12345678cdef34AB)

我认为我需要检查系统是大端还是小端,因为我的代码更改了完全相反的字节。比方说它改变了 MSB 而不是 LSB。 但是...我意识到这并不重要,因为我正在使用位。

如你所见,这里的代码改错了索引:

(!) Error in index: 0. Output: 0x123456789abcdeff
Answer: 0xff3456789abcdeab

 (!) Error in index: 1. Output: 0x123456789abcffab
Answer: 0x12ff56789abcdeab

(!) Error in index: 2. Output: 0x123456789affdeab
Answer: 0x1234ff789abcdeab

 (!) Error in index: 3. Output: 0xffffffffffbcdeab
Answer: 0x123456ff9abcdeab

 (!) Error in index: 4. Output: 0x123456789abcdeff
 Answer: 0x12345678ffbcdeab

(!) Error in index: 5. Output: 0x123456789abcffab
 Answer: 0x123456789affdeab

 (!) Error in index: 6. Output: 0x123456789affdeab
 Answer: 0x123456789abcffab

好吧,我考虑过将我的代码更改为带有数组的代码,只是为了获取一个数字 -> 运行 作为数组 -> 更改所需的索引 -> 就是这样。 但是.. 我不能正确地写它所以我坚持移动的东西(我也不能正确地写)。 这是我的尝试:

    unsigned long replaceByte(unsigned long original, unsigned char newByte, int indexToReplace){
    int size = (sizeof(unsigned long));
char a[size];
for (int i=0; i<size; i++){
if (i=0)
a[0] = original & 0xff;
else
a[i] = original>>(8*i) & 0xff;
}
a[indexToReplace] = newByte;
......// stuck
 }

我不允许使用 long long、uint_fast64_t 或 reinterpret_cast 或任何其他“外部”东西。

如果代码在 32 位系统或 64 位系统上 运行ning,我也认为我需要以某种方式进行更改,以确定哪个大小是无符号长(4 或 8 字节)。

本文以 [我的] 热门评论开头。

valuemask 需要 unsigned long.

此外,在进行转换时, 值 are/were 由于表达式提升规则而被截断 [至 32 位]。

在上面,我忘了 value 有同样的问题。


这是强制正确换档的另一种方法:

unsigned long
replaceByte(unsigned long original,unsigned char newByte,int indexToReplace)
{
    int shift = indexToReplace*8;
    unsigned long value = newByte;
    unsigned long mask = 0xff;

    value <<= shift;
    mask <<= shift;

    return (~mask & original) | value;
}

以上是平时做的。但是,以下 可能 也有效:

unsigned long
replaceByte(unsigned long original,unsigned char newByte,int indexToReplace)
{
    int shift = indexToReplace*8;
    unsigned long value = ((unsigned long) newByte) >> shift;
    unsigned long mask = ((unsigned long) 0xff) >> shift;

    return (~mask & original) | value;
}

更新:

hey thanks. The provided codes bring me the following output: 0x12345678cdef34AB instead of 0xAB345678CDEF3456. I'm pretty sure it's related to the little endian thing because it's not a coincidence that instead of the MSB the LSB gets replaced.

不是字节顺序。这就是 indexToReplace 需要解释的方式。

处理器根据有效的字节序模式获取数据,因此当我们尝试进行移位时,处理器寄存器中的值始终是大字节序[所以,不用担心]

normal/usual是索引从右开始。但是,根据 [correct] 数据,问题希望索引从左开始。

所以,我们只需要调整 index/shift:

unsigned long
replaceByte(unsigned long original,unsigned char newByte,int indexToReplace)
{
#if 0
    int shift = indexToReplace * 8;
#else
    int shift = ((sizeof(unsigned long) - 1) - indexToReplace) * 8;
#endif
    unsigned long value = newByte;
    unsigned long mask = 0xff;

    value <<= shift;
    mask <<= shift;

    return (~mask & original) | value;
}

更新#2:

It recognises the "int shift = indexToReplace * 8;" as a comment for some reason, but it still works.

那是因为 #if 0 是 CPP [预处理器] 语句。它的解释方式类似于 #ifdef NEVERWAS,我们 从不 执行 #define NEVERWAS,因此包含 #else 下的代码。

您可能希望在编译时使用 -E and/or -P 选项以查看预处理器阶段的 输出

在这种情况下,只有 编译器 会看到的东西是:

int shift = ((sizeof(unsigned long) - 1) - indexToReplace) * 8;

BUT if I try to change the "#if 0" to "#if (is_big_endian == 0)" I get a wrong result when I use "0" as the indexToReplace.

请尽量不要将此称为字节序相关。再一次,这不是而不是正在发生的事情。我发布的代码 不管 处理器字节序模式如何。

请重读有关 correct/proper 解释字节索引的部分。这就是 选择 给字节编号的方式。

再一次,在 99.44% 的情况下,它是从右侧(LSB 到 MSB)定向的。从图形上看,大多数人使用:

| MSB |     |     |     |     |     |     | LSB |
|  01 |  23 |  45 |  67 |  89 |  AB |  CD |  EF | DATA
|   7 |   6 |   5 |   4 |   3 |   2 |   1 |   0 | INDEX

但是,对于您的确切问题陈述,它是从(MSB 到 LSB)方向:

| MSB |     |     |     |     |     |     | LSB |
|  01 |  23 |  45 |  67 |  89 |  AB |  CD |  EF | DATA
|   0 |   1 |   2 |   3 |   4 |   5 |   6 |   7 | INDEX

不寻常。它也较慢,因为移位的计算更复杂。

It gives out: 0x12345678CDEF34FF instead of 0xFF345678CDEF3456

最终,无论您对#if做了什么,它都选择了不正确的方程。