2

Hey guys I have trouble converting this statement below in C to Golang. I tried debugging and I see that every 4th element in the char array is being modified and the statement is casting a char to an unsigned int so that the OR operation can take place.

I would like to know how to do this exact same operation in Golang. For the char arrays, I have decided to use uint8 arrays to store characters instead (if you know other data types that are better please let me know).

From my research, since I am planning to use the slice in Golang, I believe updating the slice headers is an option but I am not too sure how to do it.

Below is the C code and the picture shows the debugging of the char array (notice the difference in the 0 and 4th element)

#include <stdio.h>

int main()
{
    unsigned char buf[] =  {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
    unsigned char bb[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
    unsigned int state[] = {45, 45, 33, 22, 55, 55, 90};

    for(int i=0; i<7; i++)
    {
         ((unsigned int*)buf)[i] = state[2] ^ ((unsigned int*)bb)[i];
    }
    return 0;
}

enter image description here

Below is the Golang code that I have tried (the compiler error is included as a comment)

package main

func main() {
    bb := []uint8{1, 2, 3, 4, 5, 6, 7}
    buf := []uint8{1, 44, 55, 66, 66, 65, 34}
    state := []uint32{1, 66, 434, 234, 344, 434, 890}

    for i:=0; i<7; i++ {
        // ((unsigned int*)buf)[i] = state[2] ^ ((unsigned int*)bb)[i];
        uint32(buf[i]) = state[2] ^ uint32((bb)[i])
        // error: cannot assign to uint32(buf[i]) (value of type uint32)
    }
}
zahid kamil
  • 165
  • 6
  • **Don't**. `((unsigned int*)buf)[i] = state[2] ^ ((unsigned int*)bb)[i];` is undefined behavior. It [violates strict aliasing](https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule), and can also invoke undefined behavior [if the `char` value being aliased does not have any required alignment](https://port70.net/~nsz/c/c11/n1570.html#6.3.2.3p7). Note that undefined behavior is invoked just be **creating** such a pointer - dereferencing it is not required. – Andrew Henle Oct 25 '22 at 15:16

1 Answers1

0

That C code isn't portable, and that's if you ignore the fact that it invokes undefined behaviour.

Assuming an environment with 32 bit LE unsigned int values and 8 bit unsigned char values, and assuming it does what's expected even though it's undefined behaviour,

for ( int i=0; i<7; i++ ) {
   ((unsigned int*)buf)[i] = state[2] ^ ((unsigned int*)bb)[i]
}

is equivalent to

size_t n = 7;

// Convert the array of uint8_t to uint32_t.
uint32_t bb_u32[ n ];
memcpy( bb_u32, bb, n * sizeof( uint32_t ) );

// Apply a function to each uint32_t.
uint32_t buf_u32[ n ];
for ( int i=0; i<n; i++ ) {
   buf_u32[ i ] = state[ 2 ] ^ bb_u32[ i ];
}

// Convert the resulting array of uint32_t to uint8_t.
memcpy( buf, buf_u32, n * sizeof( uint32_t ) );

or

for ( int i=0; i<7; i++ ) {
   buf[ i * 4 + 0 ] = ( ( state[ 2 ] >> ( 8 * 0 ) ) && 0xFF ) ^ bb[ i * 4 + 0 ];
   buf[ i * 4 + 1 ] = ( ( state[ 2 ] >> ( 8 * 1 ) ) && 0xFF ) ^ bb[ i * 4 + 1 ];
   buf[ i * 4 + 2 ] = ( ( state[ 2 ] >> ( 8 * 2 ) ) && 0xFF ) ^ bb[ i * 4 + 2 ];
   buf[ i * 4 + 3 ] = ( ( state[ 2 ] >> ( 8 * 3 ) ) && 0xFF ) ^ bb[ i * 4 + 3 ];
}

Note that bb and buf are way too small, so unpredictable effects will occur.

Now that you understand what the code does, you should have an easier time writing the corresponding Go code. Sorry it's just a partial answer, but that's part of why you're not supposed to ask two questions in one post. (What does X do? How do I do Y in Go.)

ikegami
  • 367,544
  • 15
  • 269
  • 518