How does 0+= VARIABLE result in VARIABLE+1? - c

I ran into a strange bug when updating a counter that is used to calculate the variable for a switch statement.
int iCount was assigned zero outside of the loop, and it is the counter used for the while loop.
To update the counter inside the loop, I wrote iCount+= packedCount, where packedCount was 7 in this case. In the debugger, however, 0+=packedCount resulted in packedCount+1, which was 8. That resulted in an array slot remaining unfilled throughout the loop.
When I changed the line to icount= packedCount+iCount, the proper value was returned.
So, is this behavior unique to C, as I do this regularly in Java with no strange effects.
EDIT- Code snippet added
#define SKIP 8
#define PACKED 7
int iCount;
iCount=0;
while (iCount < characters-1){
for (packedCount=iCount; packedCount< iCount+PACKED; packedCount++){
//ASCII compressor logic goes here
}
//iCount+= packedCount; //this produces 8 for 0+packedCount
//this works
iCount= iCount+packedCount; //skip the next byte in array, since it was already packed
}

As far as the compilers are concerned
iCount += packedCount;
iCount = iCount + packedCount;
are identical. If they're producing different results, then something in your code is causing iCount to get trashed - a bad pointer reference, perhaps.

Try this, and other variations you can think of:
#define SKIP 8
#define PACKED 7
int iCount;
iCount=0;
while (iCount < characters-1){
for (packedCount=iCount; packedCount< iCount+PACKED; packedCount++){
//ASCII compressor logic goes here
}
printf("iCount after the inner loop: %d\n", iCount); /* DEBUG */
printf("packedCount after the inner loop: %d\n", packedCount); /* DEBUG */
//iCount+= packedCount; //this produces 8 for 0+packedCount
//this works
iCount= iCount+packedCount; //skip the next byte in array, since it was already packed
printf("iCount after update: %d\n", iCount); /* DEBUG */
}

Related

Why is my program accessing values of the binaryString array when I try to print "value"?

#include <stdio.h>
#include <math.h>
void MakeBinaryString(char *outString, char valueToConvert)
{
// Convert a 1-byte value to a string that shows its value in
// binary. We do this by checking to see each bit is on and
// if it is, setting the character value to '1' or '0' if not.
for (int i = 0; i < 8; i++)
{
// Is the bit a 1?
// The shifting is needed to quickly generate a power of 2
// so that we check only 1 bit at a time, starting with bit 7 // and working its way down.
if (valueToConvert & (1 << (7 - i)))
outString[i] = '1';
else
outString[i] = '0';
}
outString[8] = '\0';
}
int main(void)
{
char value = 5;
char binaryString[6];
MakeBinaryString(binaryString, value);
printf("The binary equivalent of %d is %s\n", value, binaryString);
return 0;
}
Output: The binary equivalent of 48 is 00000101
So the above code can be fixed if we increase size of binaryString array to 9. But I don't understand why value is being printed as 48. If I comment out the else block of MakeBinaryString then value is printed as 5. But with the else block, whatever value I set char value to, it is printing 48 or 49.
In the code you show, you're writing outside the bounds of binaryString, accessing 9 elements when there are only 6. This invokes undefined behaviour, anything could happen.
The reason that you see 48 or 49 in this particular case is that memory just so happens to be laid out such that the out-of-bounds writes are corrupting value.
The numeric ASCII values of '0' and '1' are 48 and 49, respectively. When you write out of bounds, you're overwriting value with one of those.
It's important to note that what you're doing isn't allowed, and could lead to any behaviour. You just got lucky in that variables are organized on the stack in such a way that the only noticeable damage is to value. Building for a different platform, with a different compiler or with different compiler options, or adding more to the program could lead to different and arbitrary results, including (but not limited to) crashes and corruption of other data used in the program.

How to make a bitwise array move one index every 30 seconds in C

I am rather new to coding and need some help with creating an array that will move to the next index every 30 seconds in C using byte operators. The goal is to be able to iterate to the next index and then loop back to the first index in 3000 second intervals. Im sort of stuck on how to proceed but any luck or direction would be greatly appreciated. Thank you to anyone willing to help.
array[3] = {var1|var2, var1|var2, var1|var3};
msleep(3000);
array[i++];
printf("The array is currently this: %d\n", array[i]
If your array has 3 elements, you can increment the index modulo 3:
#include <unistd.h>
#define ARRAY_SIZE 3
int array[ARRAY_SIZE] = {var1|var2, var1|var2, var1|var3};
unsigned i = 0;
while(true)
{
printf("The array is currently this: %d\n", array[i]);
i = (i + 1) % ARRAY_SIZE;
sleep(3);
// when to break is up to you.
}
EDIT: Addressing your comment
It's perfectly valid to use an if statement to reset the array index, however, I'm not quite following your logic in the comment. Don't forget, in C, arrays begin at index 0, not 1. You do not need to use an if statement and modular division. Using an if statement would go something like
while(true)
{
printf("The array is currently this: %d\n", array[i]);
if (i + 1 >= ARRAY_SIZE)
{
i = 0;
}
else
{
i++;
}
sleep(3);
// when to break is up to you.
}
This may even squeak out some better performance, but considering a 3 second sleep is acceptable, probably negligible (you'd have to benchmark it to know for sure).
Another thing to consider when using the modulo approach, and rightly so, is wrap around. An unsigned int on your system is most likely 4 bytes, meaning it has a max value of 232 - 1, or 4294967295. It turns out this is evenly divisible by 3, so consider what happens when you get to the upper limits of an unsigned int:
4294967293 % 3 == 1
4294967294 % 3 == 2
4294967295 % 3 == 0 // <== MAX UNSIGNED INT, +1 wraps it back to 0
0 % 3 == 0
1 % 3 == 1
// etc
This means, that if you were to wrap around, you would get index 0 twice in a row. If that's unacceptable, you definitely want to use the "if statement" method. However, there will be 4294967295 / 3 == 1431655765 iterations before wrap around, and considering your 3 second sleep, that will take more than 136 years to occur, according to my math. There's not a computer system that's ever been conceived expected to run for that long, so you're perfectly safe using the modulo approach for all practical purposes.
array[3] = {var1|var2, var1|var2, var1|var3};
while (1)
{
array[++i % 3]; /* answer */
printf("The array is currently this: %d\n", array[i]);
msleep(3000);
}
The ++ must precede the variable to be performed before expression is evaluated.
When ++ precedes the variable, it is being used as a "prefix operator".

Debug-print for loop omitting 1st value

I was debugging a low level program, I had to ensure that my array exp have all values I expect it to have. So I wrote a code snippet that prints my array to help debug it. Problem is standard library isn't available so I need to use my own code.
My code snippet:
int test=0;char val[5]={};
int l=0;
for(int k=0;exp[k]!=0;k++)
{
test=exp[k]; //taking in value
int_to_ascii(test, val);
print_char(val,2*l,0xd);
for(int m=0;val[m]!='\0';m++)//clearing out val for next iteration
val[m]='\0';
l=k*0xA0; //next line
}
exp is an integer array..
code for int_to_ascii:
if(src==0)
{
stack[i++]='\0'; //pushing NULL and 0 to stack
stack[i++]='0';
}
else
{
while(src!=0) //converting last digit and pushing to stack
{
stack[i]=(0x30+src%10);
src/=10;
i++;
}
}
i--;
len=i;
while(i>=0)
{
dest[len-i]=stack[i]; //popping and placing from left to right
i--; //inorder not to get reversed.
}
print_char works because I use it to print entire window and interface. It basically takes
char* szarray,int offset,int color.
I was yelling at my computer for nearly 2 hours because I thought my array is incorrect but it shouldn't be, but the actual problem was in this debug code.It doesn't print exp[0].
When it should output:
20480
20530
5
It just prints
20530
5
I even tried brute forcing values into exp[0]. If I give any value except 20480 into that, it will print invalid characters into first entry,like this:
20530P\. ;not exact value, demonstration purpose only
5
I think something is off in int_to_ascii, but that also is extensively used in other parts without any problems.
Any one have any idea with it?

C - Why is a for loop getting stuck when using a uint64_t counter, whereas a while loop isn't?

When I use a for loop with a uint64_t as a counter, it gets stuck forever, even though the condition seems to be well defined.
Offending MCVE
#include <stdio.h>
#include <inttypes.h>
int main() {
uint64_t i;
for (i = 15; i >= 0; i--) { printf("%"PRIu64" ", i); }
return 0;
}
Partial output
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 18446744073709551615 18446744073709551614 18446744073709551613 18446744073709551612 18446744073709551611 18446744073709551610 18446744073709551609 18446744073709551608 18446744073709551607 18446744073709551606 18446744073709551605 18446744073709551604 18446744073709551603 18446744073709551602 18446744073709551601 18446744073709551600 18446744073709551599 18446744073709551598 18446744073709551597 18446744073709551596 18446744073709551595 18446744073709551594 18446744073709551593 18446744073709551592 18446744073709551591 18446744073709551590 18446744073709551589 18446744073709551588 18446744073709551587 18446744073709551586 18446744073709551585 18446744073709551584 18446744073709551583 18446744073709551582 18446744073709551581 18446744073709551580 18446744073709551579 18446744073709551578 18446744073709551577 18446744073709551576 18446744073709551575 18446744073709551574 18446744073709551573 18446744073709551572 18446744073709551571 18446744073709551570
It seems it's ignoring the stop condition, and so it rolls over.
However, when changing it to an "equivalent" while loop, everything works fine:
Correct MCVE
#include <stdio.h>
#include <inttypes.h>
int main() {
uint64_t i = 16;
while (i--) { printf("%"PRIu64" ", i); }
return 0;
}
Complete output
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Am I missing something regarding the use of uint64_t counters in a for loop? Any help is greatly appreciated!
The condition i >= 0 is alwaays true if i is an unsigned type. Decrementing an unsigned zero will not produce a negative value, but the counter will wrap to the maximum representable number for the given type.
C represents ranges with an inclusive lower bound and an exclusive upper bound. For example, an array of N elements has indices 0 through N - 1. The upper bound itself isn't a valid array index.
This convention means that you use a value before incrementing it, but deceremt it before using it. Consider a simple stack:
stack[nstack++] = x; // push a value
x = stack[--nstack]; // pop a value
The same logic goes for loops: When you move forwards, use the value before you increment it:
for (var i = 0; i < N; i++) { use(i); }
When you move backwards, decrement first and then use it:
for (var i = N; i-- > 0; ) { use(i); }
This loop is equivalent to your while. The update section, which happens after processing the body, is empty here. The check is performed on the value before entering the loop; the loop body has the updated value.
This backwards loop might look awkward with the empty update section, but in other ways it is orthogonal to the forward version:
It uses the actual bounds; there's no need to start with N - 1;
It works equally well for arbitrary bounds as long as they follow the convention of inclusive lower and exclusive upper bound;
The test is a pure inequality, not a greater/less-then-or equal comparison.
The expression i >= 0 is always true if i is of an unsigned integer type. The alternative and simple way is to change it into:
uint64_t i;
for (i = 15; i != -1; i--) { ... }
This works no matter if i is a signed or an unsigned integer. In the uint64_t case, -1 will first get converted into 0xFFFFFFFFFFFFFFFF and then compared with i.
If you want to get rid of the compile warning, change it into:
i != (uint64_t)-1
but you need to ensure the uint64_t is exactly the type of i.

For loop with specific function

I have a small problem with a program I am working on.
My program executes a function on an array. The function only can execute the commands on the first 16 elements of the array.
I now want to make a loop so that the function can work on more than 16 elements of the array. Here's my thought, but it ended up in an infinite loop:
int l = 0;
for (int i=0; i<=size; i+16)
{
for (int j=0; j<=16;j++)
{
FUNCTION(INARRAY; OUTARRAY);
}
}
Next problem is that the function will only walk through 16 Elements of the array and ignore the rest.
What is the best way to make it walk through the next 16 elements and save it in the outbuffer as the following elements?
As I adapt the solution it still does only process through the first 16 elements and then doesn't continue with the next 16.
This:
i + 16
does nothing to change the value of i, so that loop never terminates. That expression just computes the value of i + 16, but the result is thrown away.
To change the value of a variable, use assignment (=) operator, like i = i + 16 or i += 16.
I think I have what you are looking for. You would have to implent it and check it out. Be warned though that this worked if your arrays size is a multiple of 16, otherwise there will be remaining elements paired with already processed elements.
int count16 = 0;
var tempAr[16];
for (int i=0; i<numOfArraysToGoThrough; i++)
{
tempAr[count16]=numOfArrayToGoThrough[i];
if ( count16 == 15)
{
FUNCTION (tempAr, OUTARRAY);
count16=0;
}
else
count16+=1;
}
figured this one out some time ago
here's how it worked for me
for (uint64_t i=0; i<size; i+=16)
{aes_encrypt(tfm, &tempbuffer[i], &inbuffer[i]);}
this does the following
calling aes_encrypt will encrypt the first 16 bytes of data in the array,
the for loop then jumps to the 16th entry and performs the encryption again

Resources