1

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;
}

Code link

0

3 Answers 3

4

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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.

Comments

1

The key insight is for a given binary value x:

  1. 0 | x == x
  2. 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
}

which is specialization of memchr():

someElements = memchr(array, 'y', 3);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.