Understanding C++ operator overloading - c++

I was reading the source of a hashing competition today, and came across this:
#define BYTES_IN_BLOCK 1024
struct block{
uint8_t v[BYTES_IN_BLOCK];
block(){ memset(v, 0, BYTES_IN_BLOCK); }
uint64_t& operator[](uint8_t i){ return *(uint64_t*)(v + 8 * i); }
};
Then, a little later in the code, there's this:
state = new block[cost]; // cost is a uint32_t (like 1024)
// Probably 50 lines of code.
block prev_block;
prev_block = state[foo]; // foo is a uint32_t
What I can't figure out is what this is doing. Now, I understand C, but C++ not so much. Bear with me here for a second.
This part: return *(uint64_t*)(v+8*i) should return a uint64_t, and does so when I tested it:
state->v[8*10] = 12;
uint64_t bar = *(uint64_t*)(v+8*10);
printf("%" PRIu64 "\n", bar);
So that all makes sense.
But this:
prev_block = state[foo];
Makes no sense. Since state is block*, prev_block should now "be" state, correct? But it doesn't, because their arrays are different.
state->v[8*12] = 12;
printf("%" PRIu64 "\n", (*state)[12]);
prev_block = state[12];
printf("%" PRIu64 "\n", (*(&prev_block))[12]);
So, what exactly is going on here?

You are mixing up the two operator[]s involved here. In your last example, you set state[0][12] = 12, and you're comparing it to state[12][12]. Since state is a block*, state[n] is just normal array access; it doesn't invoke the operator[] defined in block.

state = new block[cost];
prev_block = state[foo];
is analogous to:
int* arr = new int[size];
int a = arr[index];
That's basic C++. I am not sure why that is confusing.

There is confusion with a number of concepts here. I'm going to blast through all the ones I see because they are all important, not just the immediate answer.
state is a pointer to block, but state[0] should just be a block, specifically the first block in state and also the result of *state.
prev_block = state[foo];
All of the data in block is simple, just a self-contained array of bytes, so it should be directly copy-able without any special assistance. prev_block = state[foo] should copy state[foo] to prev_block. Since it's a copy, the addressing will be different.
In the printout code provided:
state->v[8*12] = 12;
Breaking his down for clarity. state-> is going to access the first element of the state array. state->v[8*12] is going to access v[8*12] of state[0]. state->v[8*12] = 12; is going to set v[8*12] of state[0]to 12. This means byte 96 of v is going to be 12. To reference a different state you can use (state + array_index)->v[8*12]; or state[array_index].v[8*12]; I find the latter more readable.
printf("%" PRIu64 "\n", (*state)[12]);
(*state) gives you the first state in the array, AKA state[0]. (*state)[12] uses state[0]'s [] operator, defined as uint64_t& operator[](uint8_t i){ return *(uint64_t*)(v + 8 * i); }
This is going to return a 64 bit int starting at the address of state[0].v[12*8] and comprised of the next 8 bytes of array v (v[96] through v[103], resulting in 12,0,0,0,0,0,0,0). This will be 12 or a god-awful big number depending on the system's endian. The wrapping printf is going to print the returned number.
prev_block = state[12];
Is going to copy the 13th element of the state array to prev_block, assuming enough blocks were created by state = new block[cost];. Nothing magical, but there shouldn't be anything there but zeros because the only state that has any values set is state[0]. You either wanted to copy state[0] here or write to state[12] up a few lines.
printf("%" PRIu64 "\n", (*(&prev_block))[12]);
the * and & cancel each other out before accomplishing anything. It will then print out the result of using the block [] operator as above. Should be zero.

Related

How to make a copy of a byte array in c code?

I have the address of the first char in my byte array, and it's size:
const char *rawImageBytes, int size
And I want to copy the content to a different byte array. and then modify that one a bit.
This is whay I am doing now:
LOGI("FrameReceived will reach here 1");
modifiedRawImageBytes = rawImageBytes;
jint sizeWH = width * height;
jint quarter = sizeWH/4;
jint v0 = sizeWH + quarter;
for (int u = sizeWH, v = v0, o = sizeWH; u < v0; u++, v++, o += 2) {
modifiedRawImageBytes[o] = rawImageBytes[v]; // For NV21, V first
modifiedRawImageBytes[o + 1] = rawImageBytes[u]; // For NV21, U second
}
But I don't get the correct colours, as if I would to this in Java, instead of c++.
And I am assuming this happens, because I just do modifiedRawImageBytes = rawImageBytes; instead of actually copying the whole byte array, so that it can start in memory from another address pointer.
A bit of a beginner with c, so I'm lost at this, can someone help me understand what is done wrong?
PS: I am assuming that, because even if I send the rawImageBytes and not the modifiedRawImageBytes, it will still be modified
This is because const char * is a pointer. This mean it represent an address. So you guessed right, the new variable represent the same datas.
To avoid this you should create a copy.
char modifiedRawImageBytes[size];
//if the pointer come from function's param don't redeclare it ;)
std::memcpy(modifiedRawImageBytes, rawImageBytes, size*sizeof(char));
This code will allocate a new char array and then memcpy will copy in the previous array data in the new array.
Note that you need to includecstdio

Setting pointer out of it's memory range

I'm writing some code to do bitmap blending and my function has a lot of options for it. I decided to use switch to handle those options, but then I needed to either put switch inside a loop (I read that it affects performance) or to assign loop for each switch case (makes code way too big). I decided to do this using third way (see below):
/* When I need to use static value */
BYTE *pointerToValue = (BYTE*)&blendData.primaryValue;
BYTE **pointerToReference = &pointerToValue;
*pointerToReference = *pointerToReference - 3;
/* When I need srcLine's 4th value (where srcLine is a pointer to BYTE array) */
BYTE **pointerToReference = &srcLine;
while (destY2 < destY1) {
destLine = destPixelArray + (destBytesPerLine * destY2++) + (destX1 * destInc);
srcLine = srcPixelArray + (srcBytesPerLine * srcY2++) + (srcX1 * srcInc);
for (LONG x = destX1; x < destX2; x++, destLine += destInc, srcLine += srcInc) {
BYTE neededValue = *(*pointerToReference + 3); //not yet implemented
destLine[0] = srcLine[0];
destLine[1] = srcLine[1];
destLine[2] = srcLine[2];
if (diffInc == BOTH_ARE_32_BIT)
destLine[3] = srcLine[3];
}
}
Sometimes I might need to use srcLine[3] or blendData.primaryValue. srcLine[3] can be accessed easily with *(*pointerToReference + 3), however to access blendData.primaryValue I need to reduce pointer by 3 in order to keep the same expression (*(*pointerToReference + 3)).
So here are my questions:
Is it safe to set pointer out of its memory range if later it is
going to brought back?
I'm 100% sure that it won't be used when it's out of range, but can
I be sure that it won't cause any kind of access violation?
Maybe there is some kind of similar alternative to use one variable
to capture a value of srcLine[3] or blendData.primaryValue
without if(), like it's done in my code sample?
Because of #2, no usage, the answer to #1 is yes, it is perfectly safe. Because of #1, then, there is no need for #3. :-)
An access violation could only happen if the pointer were actually used.

How can I know if the memory address I'm reading from is empty or not in C++?

So on an embedded system I'm reading and writing some integers in to the flash memory. I can read it with this function:
read(uint32_t *buffer, uint32_t num_words){
uint32_t startAddress = FLASH_SECTOR_7;
for(uint32_t i = 0; i < num_words; i++){
buffer[i] = *(uint32_t *)(startAddress + (i*4));
}
}
then
uint32_t buf[10];
read(buf,10);
How can I know if buff[5] is empty (has anything on it) or not?
Right now on the items that are empty I get something like this 165 '¥' or this 255 'ÿ'
Is there a way to find that out?
You need first to define "empty", since you are using uint32_t. A good ide is to use value 0xFFFFFFFF (4294967295 decimal) to be the empty value, but you need to be sure that this value isn't used to other things. Then you can test if if ( buf [ 5 ] == 0xFFFFFFFF ).
But if your using the whole range of uint32_t, then there is no way to detect if it's empty.
Another way is to use structures, and define a empty bit.
struct uint31_t
{
uint32_t empty : 0x01; // If set, then uint31_t.value is empty
uint32_t value : 0x1F;
};
Then you can check if the empty bit is set, but the negative part is that you lose a whole bit.
If your array is an array of pointers you can check to see by comparing it to {nullptr}, otherwise, you cannot unless you initialize all the initial indexes to the same value, and then check if the value is still the same.

std::copy setting pointer to null

I'm working on some code, and I have a point where I grab some amount of binary data, then want to extract some bytes from it. So, I have the following:
unsigned char * payload;
int payload_size;
uint32_t major = 0, minor = 0;
payload = out_resp.get_payload(&payload_size); // Retrieve the data, return a pointer
if(payload_size >= 8) { // Need at least 8 bytes in the payload
std::copy(payload, payload + 4, &major);
std::copy(payload + 4, payload + 8, &minor);
}
As you can see, the first four bytes from the payload should be placed in major, and the next four in minor. However, while going through debugging, I'm noticing that after the first std::copy, my variable payload is set to NULL!
Is this expected behavior for std::copy, or is something going wrong? Should I avoid this by simply creating another pointer, and passing that to std::copy?
std::copy doesn't work like memcpy. Your std::copy(payload, payload + 4, &major); will copy:
(&major)[0] = payload[0];
(&major)[1] = payload[1];
(&major)[2] = payload[2];
(&major)[3] = payload[3];
And that's not what you need. (&major)[1] is outside the bounds, so assigning to it causes undefined behavior.

Odd behaviour with byte[] C++

I have been writing some code to create a byte array I will be sending over a socket to another process. However noticed some really odd behavior regarding my byte[].
The cout at the end prints out 99, however looking at my code, I couldn't find where the value is being set. I create a char array of size sendingSize which is a constant. I don't set the value 307200* 3 so I don't understand how it prints out with a value...
char tosend[sendingSize];
//Send over the frame
for(int i = 0; i < 307200; i++)
{
tosend[i * 3] = (byte)imCopy[i/640][i%640].red;
tosend[i * 3+1] = (byte)imCopy[i/640][i%640].green;
tosend[i * 3+2] = (byte)imCopy[i/640][i%640].blue;
}
char *bytePointer = tosend;
cout<<(int)tosend[307200* 3]<<endl;
Your code does not write any value into index 307200*3 (because the highest index your for loop reaches is 307199). So you are reading some byte from memory beyond the declared size of your array. This is undefined behaviour and anything could happen.
Some other programming languages (such as Java) do automatic range checking on arrays and would throw an exception in this case. In C++, you are expected to do the right thing and the compiler doesn't generate range checking code for you.