Why does this retyped code not work the same as the original?

1

I'm studying C ++ a short time and I want to train rewriting functions already done by me in C # only in C ++.

I wrote a simple code that calculates a IV of a hash, very simple even, calling the same methods using the same argument in both methods the returns are different and I do not understand why.

CalcIV(byte[] data) in C # :

    public static byte CalcIV(byte[] pass) {
        int iv = 0;
        foreach(byte k in pass) {
            iv += k;
            iv *= k + 1;
        }
        return (byte)(iv / pass.Length);
    }

calc_iv(byte buffer[]) in C ++ :

#include <iostream>

typedef unsigned char byte;

byte calc_iv(byte buffer[])
{
    int iv = 0;
    size_t len = sizeof(buffer); // get buffer size
    for(int i = 0; i < len; i++) {
        byte I = buffer[i];
        iv += I;
        iv *= I + 1;
    }
    return iv / (len);
}

And what is returned is as follows:

// Em C#
byte[] data = new byte[] {41, 32, 16};
return CalcIV(data);
// Resultado é 152

// Em C++
byte buf[] = {41, 32, 16};
byte iv = calc_iv(buf);
return iv;
// Resultado é 50

Both results should be the same, but I do not understand why in C # the same code gives 152 and C + + gives 50 .

Does anyone explain me?

    
asked by anonymous 21.12.2017 / 23:03

1 answer

4
  

and in C ++ gives 50.

However, because the program has an undetermined behavior, it can soon give any value as a result, something that can confirm here

p>

The problem is here:

size_t len = sizeof(buffer); // get buffer size

Since an array in C is a pointer to the first element, this sizeof gets only the size of the pointer buffer , which will usually be 4 bytes. In this situation, for executes 4 times and accesses an element outside the array, thus getting a random value in memory.

You can solve this problem in some ways:

  • Passing the size also as a parameter:

    This is a common solution in pure C, where functions that use arrays are always given their size. An exception would be a string since the end can be determined by 'main' .

    byte calc_iv(byte buffer[], size_t len)
    {
        int iv = 0;
        for(int i = 0; i < len; i++) {
           byte I = buffer[i];
           iv += I;
           iv *= I + 1;
       }
       return iv / (len);
    }
    

    And calling sizeof(buf) like this:

    byte iv = calc_iv(buf, sizeof(buf)/sizeof(buf[0]));
    

    In main the compiler is able to determine the total size of the allocated vector because a static allocation is made, so vector will give the total size of the array in bytes, which, when divided by the size of the first element in bytes, of array elements.

    The same can no longer be done within the function because there is no way to know how the array was constructed, and the array does not have any associated size information. It is merely a pointer to the first element.

    See this code running on Ideone

  • Passing only a vector

    This scenario is most similar to C # because #include <vector> has size information internally, so it is not necessary to send any more information:

    #include <iostream>
    #include <vector>
    
    typedef unsigned char byte;
    
    byte calc_iv(std::vector<byte> buffer)
    {
        int iv = 0;
        for(int i = 0; i < buffer.size(); i++) {
            byte I = buffer[i];
            iv += I;
            iv *= I + 1;
        }
        return iv / buffer.size();
    }
    
    
    int main(){
        std::vector<byte> buf = {41, 32, 16};
        byte iv = calc_iv(buf);
        std::cout<<(int)iv<<std::endl;
    
       return 0;
    }
    

    See this example also in Ideone

    In this case it was necessary to add len to the top, and buffer.size() was changed directly by vector .

    In order to instantiate main in %code% the way I did it has to compile with C ++ 11 or higher.

  • 21.12.2017 / 23:50