This program displays certain messages when some of the elements are 'y'
or if all of the elements are 'n'
.
My question is about this line: someElements |= array[i] == 'y'
.
I understand that it can be written in this way: someElements = someElements | array[i] == 'y'
.
I'm just asking for an explanation why does it work?
#include <stdio.h>
int main()
{
char array[3] = { 0 };
int i;
for (i = 0; i < 3; i ) {
do {
printf("\nElement No.%d [y/n]: ", i 1);
scanf(" %c", &array[i]);
if (array[i] != 'y' && array[i] != 'n') {
printf("Must be a lowercase 'y' or 'n'\n");
}
} while (array[i] != 'y' && array[i] != 'n');
}
int someElements = 0;
for (i = 0; i < 3; i ) {
someElements |= array[i] == 'y';
}
if (someElements) {
printf("\nSOME of the elements = y.\n");
}
else{
printf("\nNONE of the elements = y.\n");
}
return 0;
}
CodePudding user response:
The result of array[i] == 'y'
is a boolean true or false. It can be implicitly converted to the int
value 1
or 0
(respectively).
Then it's easy to create a bitwise OR table for the possible combinations of someElements | array[i] == 'y'
:
someElements |
array[i] == 'y' |
someElements | array[i] == 'y' |
---|---|---|
0 |
0 |
0 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
So if any of the values are 1
then the result will be 1
.
From this follows that if any of the characters in the array is equal to 'y'
then the end result of someElements
after the loop will be 1
. Which then can be implicitly converted back to a boolean true in the following if
condition.
CodePudding user response:
Bitwise OR:
Returns true if either bit is true.
Truth table:
A | B | A | B
-------------
0 | 0 | 0
1 | 0 | 1
0 | 1 | 1
1 | 1 | 1
From this, we can conclude that
someElements = someElements | array[i] == 'y;
as someElements
has been initialized with 0, or false
, it will remain false
until array[i] = 'y'
returns 1, or true
.
Aside: On the last iteration, i 1
would access out of bounds memory.
CodePudding user response:
The key insight is for a given binary value x
:
0 | x == x
1 | x == 1
We initialize the variable someElemenets
to 0 (false) so we are in the first case. someElemenets
will remain 0 till we encounter an 'y' in the array. It now becomes 1 and will remain so irregardless of the remaining input. Think of it as a one-way (light) switch.
You could just terminate the loop early instead:
someElements = 0;
for (i = 0; i < 3 && !someElements; i ) {
someElements = array[i] == 'y';
}
and it even clearer if you write it as a function:
int any_y(size_t n, const char array[n]) {
for(size_t i = 0; i < n; i )
if(array[i] == 'y') return 1
return 0
}
or just do:
someElements = memchr(array, 'y', 3);