So I'm using the following code:
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;
}
I have a given word with |w| bytes.
- Bytes are numbered from 0(least significant) to w/8-1(most significant).
For example:
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)
I thought I need to check whether the system is a big endian or a little endian because my code changes the exact opposite bytes. Lets say for example it changes the MSB instead of the LSB. But... I realized that it does not matter because i'm working with bits.
As you can see, the code here changes the wrong index:
(!) 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
Well, I thought about changing my code to something with arrays, just to get a number -> run on it as an array -> change the needed index -> and that's it. But.. I couldn't write it correctly so I stick to the shifting thing (which I can't write correctly as well). This is my attempt:
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
}
I'm not allowed to use long long, uint_fast64_t or reinterpret_cast or any other "externals" things.
I also think I need to change somehow if the code is running on a 32 bit system or a 64 one in order to determine which size is the unsigned long (4 or 8 bytes).
This is prefaced by [my] top comments.
valueandmaskneed to beunsigned long.Also, when doing the shift, both values are/were getting truncated [to 32 bit] due to expression promotion rules.
In the above, I forgot about
valuehaving the same problem.Here's an alternate way to force correct shifting:
The above is what I usually do. But, the following may also work:
UPDATE:
It's not an endian thing. It's how
indexToReplaceneeds to be interpreted.The processor fetches according to the endian mode in effect, so by the time we try to do the shift, the value in the processor register is always big endian [so, no worries]
The normal/usual is that the index starts from the right. But, according to the [correct] data, the problem wants the index to be from the left.
So, we just need to adjust the index/shift:
UPDATE #2:
That is because
#if 0is a CPP [preprocessor] statement. It is interpreted in a manner similar to#ifdef NEVERWASwhere we never do a#define NEVERWAS, so the code under the#elseis what is included.You may wish to use the
-Eand/or-Poptions when compiling to see the output of the preprocessor stage.In this instance, the only thing that the compiler will see is:
Please try to get beyond referring to this as endian related. Once again, that is not what is happening. The code I've posted works regardless of the processor endian mode.
Please reread the part about the correct/proper interpretation of the byte index. It is how one choses to number the bytes.
Once again, 99.44% of the time, it is oriented from the right (LSB to MSB). Graphically, most people use:
However, for your exact problem statement, it is oriented from the left (MSB to LSB):
This is unusual. It is also slower because the calculation of the shift is more complex.
Ultimately, whatever you did to the
#if, it chose the incorrect equation.