How this for loop works? - c

I am new to the C programming. I came across the for loop example.
I don't understand some part of the loop. Output is 8. I don't get how b is incremented till 4.
Here is my code:
int a = 4;
int b = 2;
int result = 0;
for(int count = 0; count != b; count++) {
result = result + a;
}
printf("a times b is %i\n", result);
return 0;

Sometimes, the easiest thing to do is to get the program to explain itself:
#include <stdio.h>
#include <stdlib.h>
int main(void){
int a = 4;
int b = 2;
int result = 0;
for(int count = 0; count != b; count++) {
printf("a = %3d, b = %3d, count = %3d, result = %3d\n", a, b, count, result);
result = result + a;
printf("a = %3d, b = %3d, count = %3d, result = %3d\n", a, b, count, result);
}
printf("a = %3d, b = %3d\n", a, b);
printf("a times b is %i\n", result);
return 0;
}
Output
a = 4, b = 2, count = 0, result = 0
a = 4, b = 2, count = 0, result = 4
a = 4, b = 2, count = 1, result = 4
a = 4, b = 2, count = 1, result = 8
a = 4, b = 2
a times b is 8
As you can see, b does not change. count changes and the loop is exited when count is equal to b.

The variable b is not incremented, the variable count starts from 0 and incremented in the for loop. When the count variable becomes 2 the loop ends. So, the loop runs twice (count 0 and count 1) and the result is 4 + 4 = 8.

At first, count = 0 which is not the same with b = 2 and so the loop starts. By doing so, the first iteration of loop gives a result,
result = 0 + 4
Since the loop ends and count variable should proceed count++ which means count = count + 1. Thus, count = 0 + 1 = 1 where it is not the same valeu with b = 2 again.
Proceed the loop again,
result = 4 + 4 # where the first number came from the result of first loop
Now count++ makes count = 2 which is now same value with b = 2. Then, the condition of the loop is not matched, count != 2, no further loop and print the value result = 8.

it will be executed 2 times
count= 0 ==> result=0+4
and count =1 ==> result=4+4 ==> result=8
when it will reach count= 2 the 2!=2 part will be false and we will exit the for loop

The loop runs only two times we can dry run the loop like that:
Initial values for variables: -> a = 4, b = 2, count = 0 and result = 0
loop first run ->
count = 0
count != 2 -> that is -> 0 != 2 => true
result = result + a -> 0 + 4 = 4
second run ->
count = 1
count != b -> that is -> 1 != 2 => true
result = result + a -> 4 + 4 = 8
third run ->
count = 2
count != b -> that is -> 2 != 2 => false
stop loop.
And the final resultent values are as follow: a= 4, b= 2 , count = 2 and result = 8

Related

Understanding the math of loops in C

I have these three codes, which do work, but they're not printing what I expected them to print. I don't think I properly understand the math/precedence here and was wondering if someone could help me comprehend.
CODE A
int a;
int b = 1;
for (a = 1; a < b + 4; b++, a = b * 2)
printf("%i\n", a);
I expected it to print out 4, 5. but it's 3, 9. I understand that's correct -- but why?
CODE B.
int a = 5;
int b = 0;
while (a > 3)
{
b += a;
--a;
}
printf("%i, %i\n", a, b);
Admittedly I struggled figuring out the math. It prints out 3, 9 --- but I don't get why.
CODE C.
int a;
int b;
for (a = 7, b = 2; b < a; a++)
b += a - 2;
printf("%d, %d\n", b, a);
This prints out 13, 9 but I got 11, 7.
Let's step through the first loop:
for (a = 1; a < b + 4; b++, a = b * 2)
printf("%i\n", a);
First, we execute the initialization statement, which gives us a=1 and b=1 (b was set earlier in the code).
We execute the test expression (a < b + 4, which is 1 < 1 + 4), which is true, so we continue
We execute the loop body. We haven't performed any operations on a yet, so a is still equal to 1 so our output is:
1
Now execute the update expression, b++, a = b * 2. This
increments b (giving us b=2), and then sets a = b * 2, so a = 4.
We execute the test expression, and 4 < 2 + 4, so we continue.
We execute the loop body, which gives us as output:
4
We execute the update expression. We increment b, giving us
b=3, and then set a = b * 2, giving us a = 6.
We execute the test expression, and 6 < 3 + 4, so we continue.
We execute the loop body, giving us as output:
6
We execute the update expression. We increment b, giving us
b=4, and then set a = b * 2, giving us a = 8.
We execute the test expression. 8 < 4 + 4 is false, so we exit
the loop.
You can walk through a similar process for the other loops.
What might be part of the source of confusion is that a for loop in c will execute until the first semicolon found in the source code if there is not a surrounding pair { ... } to delineate several lines of code. For code A, the stuff after the second semicolon in the for loop is executed on every iteration and the printf statement is executed on every iteration too. In the last code snippet, code C. The printf is only executed after all the iterations of the for loop have completed. The same is true of the while loop in code snippet B, the printf executes after the while terminates. The while loop use of {...} delimiting characters makes this more obvious to the reader while the for loops do not.
Of course you still need to work through the calculations themselves too-which are also fairly tricky.
A for loop consists of the following structure:
for ( init; condition; increment ) {
statement(s);
}
As for how this actually executes, it is exactly equivalent to the following:
init;
while(condition) {
statement(s);
increment;
}
So, if we have the following code (CODE A):
int a;
int b = 1;
for (a = 1; a < b + 4; b++, a = b * 2)
printf("%i\n", a);
That means:
init: a = 1
condition: a < b + 4
increment: b++, a = b * 2
statement(s): printf("%i\n", a);
We can translate that into a while loop by substituting:
int a;
int b=1;
a = 1;
while(a < b + 4) {
printf("%i\n", a);
b++, a = b * 2;
}
Now, we can trace the execution step by step to see what's happening.
First loop:
1. b=1
2. a=1
3. a < b + 4
1 < 1 + 4
1 < 5
true
4. Output: 1
5. b++
b = b + 1
= 1 + 1
= 2
6. a = b*2
= 2*2
= 4
Second loop:
1. a < b + 4
4 < 2 + 4
4 < 6
true
2. Output: 4
3. b++
b = b + 1
= 2 + 1
= 3
4. a = b*2
= 3*2
= 6
Third loop:
1. a < b + 4
6 < 3 + 4
6 < 7
true
2. Output: 6
3. b++
b = b + 1
= 3 + 1
= 4
4. a = b*2
= 4*2
= 8
Fourth loop:
1. a < b + 4
8 < 4 + 4
8 < 8
false
2. End
Looking at Code A:
int a;
int b = 1;
for (a = 1; a < b + 4; b++, a = b * 2)
printf("%i\n", a);
b is set to 1;
a is set to 1;
a (1) is less than b + 4 (5), so the loop executes the printf(), printing 1;
b is incremented to 2; a is set to 4 (b * 2);
a (4) is less than b + 4 (6), so the loop executes the printf(), printing 4;
b is incremented to 3; a is set to 6 (b * 2);
a (6) is less than b + 4 (7), so the loop executes the printf(), printing 6;
b is incremented to 4; a is set to 8 (b * 2);
a (8) is not less than b + 4 (8 too), so the loop terminates.
You can apply a similar technique to the other cases.
Looking at Code B:
int a = 5;
int b = 0;
while (a > 3)
{
b += a;
--a;
}
printf("%i, %i\n", a, b);
a is set to 5;
b is set to 0;
a (5) is greater than 3 so the loop body executes;
b (0) has a (5) added to it, so it becomes 5;
a is decremented, so it becomes 4;
a (4) is greater than 3 so the loop body executes;
b (5) has a (4) added to it, so it becomes 9;
a is decremented, so it becomes 3;
a (3) is not greater than 3 so the loop terminates;
The printf() statement prints a then b, so the result is 3, 9.
Looking at Code C:
int a;
int b;
for (a = 7, b = 2; b < a; a++)
b += a - 2;
printf("%d, %d\n", b, a);
a is set to 7;
b is set to 2;
b (2) is less than a (7), so the loop executes the assignment operator;
a - 2 is 5 so b is set to 7 (2 + 5);
a is incremented to 8;
b (7) is less than a (8), so the loop executes the assignment operator;
a - 2 is 6, so b is set to 13 (7 + 6);
a is incremented to 9;
b (13) is not less than a (9), so the loop terminates;
The printf() statement prints b then a, so the result is 13, 9.

Please run this code and tell me why got this result

why the result of " (num >> i)& 1 " is 1 for the second loop?
main() {
char num = 5 ;
int i , count = 0 ;
for(i=0;i<8;i++){
if ((num >> i)& 1 )
count++;
}
printf("%d", count);
}
For starters pay attention to that the variable num itself is not being changed within the for loop
for(i=0;i<8;i++){
if ((num >> i)& 1 )
count++;
}
Its binary representation is
00000101
(Note take into account that the declaration
char num = 5 ;
differs from the declaration
char num = '5' ;
end note.)
In the first iteration of the loop when i is equal to 0 the shift operator has no effect so the if statement evaluates to logical true and the variable count will be incremented.
The variable count also will be incremented when i is equal to 2.
So as a result you will get that count is equal to 2 because in the internal representation of the variable num only two bits are set..
To make it more clearer rewrite the program the following way
#include <stdio.h>
int main(void)
{
char num = 5 ;
int count = 0 ;
for ( int i = 0; i < 8; i++ )
{
int result = (num >> i)& 1;
printf( "i = %d, result = %d\n", i, result );
if ( result ) count++;
}
printf( "\ncount = %d\n", count );
}
The program output is
i = 0, result = 1
i = 1, result = 0
i = 2, result = 1
i = 3, result = 0
i = 4, result = 0
i = 5, result = 0
i = 6, result = 0
i = 7, result = 0
count = 2
In fact the output from top to bottom shows the internal representation of the variable num starting from its less significant bit to the most significant bit.

Loop through odd numbers and 2

Is it possible in C to have a fast for/while loop that loops through the odd numbers and 2? Without using arrays.
So I'd like it to loop through {1, 2, 3, 5, 7, 9, ..}
Of course. Here is a pretty straight forward way.
for(int i=1; i<N; i++) {
if(i>3) i++;
// Code
}
A bit more hackish variant:
for(int i=1; i<N; i+=1+(i>2)) {
// Code
}
But I think in this case that the most readable variant would be something like:
// Code for 1 and 2
// Then code for 3,5,7 ...
for(int i=3; i<N; i+=2) {
// Code
}
Another option
for(int i=1;;++i) // you didn't specify a limit
{
switch(i)
{
default:
if(!(i&1))continue;
case 1:
case 2:
DoSomething(i):
}
}
Another alternative which does use an array but only a small one that is a constant size of two elements no matter how many numbers in the sequence would be:
{
int i;
int iray[] = {1, 2};
int n = 15;
for (i = 1; i < n; i += iray[i > 2]) {
printf (" i = %d \n", i);
// code
}
}
which produces:
i = 1
i = 2
i = 3
i = 5
i = 7
i = 9
i = 11
i = 13
Extending this alternative to other sequences
And this alternative can be extended to other sequences where there is a change of a similar nature. For instance if the desired sequence was
1, 2, 3, 5, 8, 11, ..
Which involves several changes in the sequence. Beginning at 1 an increment of 1 is used followed by a first increment change beginning at 3 where an increment of 2 is used followed by a second change in the sequence beginning at 5 where an increment of 3 is used, you can make the following modification.
{
int i;
int iray[] = {1, 2, 3}; // increment changes
int n = 15;
// calculate the increment based on the current value of i
for (i = 1; i < n; i += iray[(i > 2) + (i > 3)]) {
printf (" i = %d \n", i);
// code
}
return 0;
}
which would produce:
i = 1
i = 2
i = 3
i = 5
i = 8
i = 11
i = 14
#include <stdio.h>
int main()
{
for(unsigned x = 0; x < 10; x++)
printf("%u%s element - %u\n",x + 1, !x ? "st" : x == 1 ? "nd" : x == 2 ? "rd" : "th", !x + x * 2 - (x >= 2));
return 0;
}
no jumps calculating in the !x + x * 2 - (x >= 2) so no pipeline flushes.

Unexpected Output involving array values with post and pre-increment

Shouldn't the output of following program be -
2 3 20
instead it is showing
3 2 15
Can anyone explain the reason behind this?
#include<stdio.h>
main()
{
int a[5] = {5,1,15,20,25};
int i,j,m;
i = ++a[1];
j = a[1]++;
m = a[i++];
printf("%d %d %d",i,j,m);
}
3 2 15
is the correct output.
i is 3, because i became 2 in i = ++a[1]; for pre-increment and then it got post-incremented in m = a[i++];
j is 2, because j = a[1]++;, no changes afterwards.
m is 15 because m = a[i++]; i is being post-incremented, the old value of i (which is 2) is used in indexing and the post-increment on i is sequenced after the evaluation of the = statement.
Having said that, the recommended signature of main() is int main(int argc, char *argv[]) or at least, int main(void).
At this point, values of variables are:
a = {5,1,15,20,25};
i = uninitialized
j = uninitialized
m = uninitialized
Now,
i = ++a[1];
Gets the value of a[i] which is 1, increments it and it becomes 2, and then, it is stored in i.
At this point, values of variables are:
a = {5,2,15,20,25};
i = 2
j = uninitialized
m = uninitialized
Next,
j = a[1]++;
Gets the value in a[1] which is 2 (since it was incremented in the previous statement), stores this value in j and then, increments the value stored in a[1].
At this point, values of variables are:
a = {5,3,15,20,25};
i = 2
j = 2
m = uninitialized
Then,
m = a[i++];
Gets the value in a[i](a[2] since i is currently 2) which is 15 and this value is stored in m. Then, i is incremented.
At this point, values of variables are:
a = {5,3,15,20,25};
i = 3
j = 2
m = 15
3 2 15 is correct
#include<stdio.h>
main()
{
int a[5] = {5,1,15,20,25};
int i,j,m;
i = ++a[1];
j = a[1]++;
m = a[i++];
printf("%d %d %d",i,j,m);
}
Now lets go line by line assume i , j , m equals 0 {better to initialize}
from line 3 , i = ++a[1];
i = 2 as (++ pre increment , change then use , and a[1] = 1 so , i = 2)
from line 4, j = a[1]++;
j = 2 as (++ here is post increment , use then change , a[1] becomes 3 but j is equals to 2)
from line 5, m = a[i++];
i = 2 by line 3 , here ++ post increment then i will increment to 3 but a[2] will be used .
Hence i = 3 , j = 2 , m = 15
Hope you got it ..........

creating pthreads in loop and passing incremented arguments, threads are not using the correct argument values

I am creating a program that reads in a file of matrices. I store these matrices in a struct with an array of structs containing an array of the matrix values (ex: matrixArray.array -> matrix.array). I then create multiple threads that calculate the product of each row for 2 matrices. I have created a counter that is passed as an argument in pthread_create() that tells the thread which matrices to use, and which row in those matrices. I am printing out the results of this counter in the loop that calls pthread_create(), and the results I am getting are correct. However, I am also printing the values inside the function pthread_create() calls, and the values don't always match. It will skip some of the numbers, and will duplicate others.
Here is my main function:
int main(int argc, char *argv[]) {
pthread_t * tid; /* the thread identifier */
pthread_attr_t attr; /* set of attributes for the thread */
int i; // Counter
int aIndex; // Index of the current 'A' matrix being multiplied.
int rows,cols;
int array[2];
// Check to make sure we have the correct number of arguments supplied
// when running the program.
if(argc < 1){
printf("Error: You did not provide the correct number of arguments.\n\n");
return 0;
}
// Read the file and create the matrices
readFile();
// Get the default attributes
pthread_attr_init(&attr);
// Initialize the mutex lock
pthread_mutex_init(&lock, NULL);
// Set the current set to be mutliplied to 1
currentSet = 1;
// Allocate size of tid array based on number of threads
tid = malloc(threads * sizeof(pthread_t));
// Create the threads.
for(i = 0; i < threads; i++){
pthread_mutex_lock(&lock); // Lock the global variable so no other threads can access it
aIndex = ((currentSet * 2) - 2);
array[0] = currentSet;
array[1] = mtx.array[aIndex].multRow;
//pthread_mutex_unlock(&lock); // Unlock the global variable so other threads can access it.
// This prints the values stored in array. Array is passed inside pthread_create
// 0 is the set of matrices that are to be multiplied together, with each
// set containing 2 matrices, an A matrix and a B matrix.
// 1 represents the row in the A matrix that should be multiplied with matrix B
printf("0 = %i, 1 = %i aIndex = %i\n",array[0],array[1],aIndex);
pthread_create(&tid[i], &attr, runner, array);
// Increment currentSet when the current row evalutated
// in the current set is equal to the total number of rows available.
//pthread_mutex_lock(&lock); // Lock the global variable so no other threads can access it.
mtx.array[aIndex].multRow++;
if(mtx.array[aIndex].multRow == mtx.array[aIndex].rows){
currentSet++;
}
pthread_mutex_unlock(&lock); // Unlock the global variable so other threads can access it.
}
// Wait for threads to finish
for(i = 0; i < threads; i++){
pthread_join(tid[i], NULL);
}
// Print the matrices
printMatrices();
// Clean up the mutex when we are done with it.
pthread_mutex_destroy(&lock);
exit(0);
} // End of main()
mtx is a matrixArray struct that contains an array of matrix structs defined as:
typedef struct matrix {
int rows;
int cols;
volatile int multRow; // The "MULTIPLIED ROW" This is for determing which row the current thread needs to use for multiplication. This only applies for Matrix A in each set.
int size;
int set; // This is for which set the matrix belongs to.
char letter; // This is for labeling the matrices A B and C
int * array;
unsigned int * threadID; // Array containing the thread ids that are used to create the result
} matrix;
typedef struct matrixArray {
int size;
matrix * array;
} matrixArray;
My runner function, which is the function that pthread_create calls, is defined as:
void *runner(void *param) {
int * array = (int*)param;
int pSet = array[0];
int multRow = array[1];
unsigned int threadID = (unsigned int)pthread_self();
printf("set = %i row = %i worker thread = %u\n",pSet,multRow,(unsigned int)pthread_self());
// Do the matrix multiplication for a single row
// The matrices are stored globally, so we do not need to pass that data.
// However, we do want to pass in a reference to which matrices we want to
// multiply.
// The matrices we are dealing with are ((pSet * 2) - 2) and ((pSet * 2) - 1)
// Need to create a new matrix C that will store the result of the matrix multiplication
int rows, cols; // The dimensions of the matrix C.
int aIndex, bIndex, cIndex; // The index of the matrices in the array.
int i, r, c; // Counters
int result; // This stores the result of the multiplication
int aValueIndex, bValueIndex, cValueIndex; // These store the index of the value to be multiplied in each matrix
aIndex = ((pSet * 2) - 2);
bIndex = ((pSet * 2) - 1);
pthread_mutex_lock(&lock); // Lock the global variables so no other thread can access it.
rows = mtx.array[aIndex].rows;
cols = mtx.array[bIndex].cols;
// First we need to check if the matrix C for this set has been created.
for(i = 0; i < mtxResults.size; i++){
if(mtxResults.array[i].set == pSet){
//printf("Found Set %i\n",i);
cIndex = i; // Store the index to this matrix
break;
}
}
// Now it is time to multiply the matrix row
for (c = 0; c < cols; c++){
for (r = 0; r < mtx.array[bIndex].rows; r++){
// Need to calculate the location of the values we want to multiply
// Value in matrix A is going to be the current row 'r' from the
// counter plus the current row being evaluated by this thread * the
// total number of columns of matrix A.
// Value in matrix B is 'c' + (r * total number of columns in B)
// Multiply the values at those two locations and add them to the
// running result.
//aValueIndex = r + (mtx.array[aIndex].multRow * mtx.array[aIndex].cols);
aValueIndex = r + (multRow * mtx.array[aIndex].cols);
bValueIndex = c + (r * mtx.array[bIndex].cols);
result = result + (mtx.array[aIndex].array[aValueIndex] * mtx.array[bIndex].array[bValueIndex]);
}
// Now place the value in the C matrix after calculating the location
// to place the value.
//cValueIndex = c + (mtx.array[aIndex].multRow * mtx.array[bIndex].cols);
cValueIndex = c + (multRow * mtx.array[bIndex].cols);
mtxResults.array[cIndex].array[cValueIndex] = result;
// Reset result
result = 0;
}
// Store the threadID in the result matrix
mtxResults.array[cIndex].threadID[mtx.array[aIndex].multRow] = threadID;
pthread_mutex_unlock(&lock); // Unlock the global variables so other threads can access it.
pthread_exit(0);
}
The printf() statement 5 lines in to runner is where I am printing the values that are passed to the function, and they don't always match. Here is some output for the program:
0 = 1, 1 = 0 aIndex = 0
0 = 1, 1 = 1 aIndex = 0
0 = 1, 1 = 2 aIndex = 0
0 = 2, 1 = 0 aIndex = 2
0 = 2, 1 = 1 aIndex = 2
0 = 2, 1 = 2 aIndex = 2
0 = 2, 1 = 3 aIndex = 2
0 = 3, 1 = 0 aIndex = 4
set = 3 row = 0 worker thread = 3913365824
0 = 3, 1 = 1 aIndex = 4
0 = 3, 1 = 2 aIndex = 4
0 = 3, 1 = 3 aIndex = 4
0 = 3, 1 = 4 aIndex = 4
0 = 4, 1 = 0 aIndex = 6
0 = 4, 1 = 1 aIndex = 6
0 = 4, 1 = 2 aIndex = 6
set = 4 row = 2 worker thread = 3923855680
set = 4 row = 2 worker thread = 3934345536
set = 4 row = 2 worker thread = 3944835392
set = 4 row = 2 worker thread = 3955325248
set = 4 row = 2 worker thread = 3965815104
set = 4 row = 2 worker thread = 3976304960
set = 4 row = 2 worker thread = 3986794816
set = 4 row = 2 worker thread = 3997284672
set = 4 row = 2 worker thread = 4007774528
set = 4 row = 2 worker thread = 4018264384
set = 4 row = 2 worker thread = 4028754240
set = 4 row = 2 worker thread = 4039244096
set = 4 row = 2 worker thread = 4049733952
set = 4 row = 2 worker thread = 4060223808
0 = 4, 1 = 3 aIndex = 6
0 = 4, 1 = 4 aIndex = 6
0 = 4, 1 = 5 aIndex = 6
0 = 4, 1 = 6 aIndex = 6
0 = 4, 1 = 7 aIndex = 6
0 = 4, 1 = 8 aIndex = 6
0 = 4, 1 = 9 aIndex = 6
set = 4 row = 9 worker thread = 4070713664
set = 4 row = 9 worker thread = 4081203520
set = 4 row = 9 worker thread = 4091693376
set = 4 row = 9 worker thread = 4102183232
set = 4 row = 9 worker thread = 4112673088
set = 4 row = 9 worker thread = 4123162944
set = 4 row = 9 worker thread = 4133652800
0 = 5, 1 = 0 aIndex = 8
0 = 5, 1 = 1 aIndex = 8
0 = 5, 1 = 2 aIndex = 8
0 = 5, 1 = 3 aIndex = 8
0 = 5, 1 = 4 aIndex = 8
0 = 5, 1 = 5 aIndex = 8
0 = 5, 1 = 6 aIndex = 8
set = 5 row = 6 worker thread = 4144142656
set = 5 row = 6 worker thread = 4154632512
set = 5 row = 6 worker thread = 4165122368
set = 5 row = 6 worker thread = 4175612224
set = 5 row = 6 worker thread = 4186102080
set = 5 row = 6 worker thread = 4196591936
set = 5 row = 6 worker thread = 4207081792
0 = 6, 1 = 0 aIndex = 10
0 = 6, 1 = 1 aIndex = 10
0 = 6, 1 = 2 aIndex = 10
0 = 6, 1 = 3 aIndex = 10
set = 6 row = 3 worker thread = 4217571648
set = 6 row = 3 worker thread = 4249041216
set = 6 row = 3 worker thread = 4238551360
set = 6 row = 3 worker thread = 4228061504
The lines that begin with 0 are the ones that are printed in the for loop in the main function. They are exactly what I expect them to be. They are being passed to the runner function where they are being passed again, but as you can see, some of the values are skipped, while others are duplicated. In the 2 different outputs, 0 = set and 1 = row, so there should have been one set/row pair matching each 0/1 pair.
I should also note that my program worked perfectly when not using threads, and also when only creating one thread at a time and waiting for it to finish before creating a new thread.
This is a homework assignment that is do in a few hours (I have been working on this for a week, and just got passed some other road blocks), so any help would be greatly appreciated! Thank you!
You cannot use a single array to pass values into multiple threads because every thread is reading the same array.
To make this work better create a struct with all of the data each thread needs. Then make an array of those structs, one array entry for each thread. Pass each thread a pointer to ONE of those structs.
That way each thread has access to its own information and will not read or write another thread's info.

Resources