Link to home
Start Free TrialLog in
Avatar of Maarten Bruins
Maarten Bruins

asked on

What is the definition of a flag?

I started with asking what the different is between "mode" and "flag", see: https://www.experts-exchange.com/questions/29122213/What-is-the-difference-between-mode-and-flag.html

However, I see that people are using different definitions for a flag. So it's better to start with the question: what is the definition of a flag? I'm not asking for general definitions, or your own definition, but specifically use the definitions in this post (and if necessary correct them and tell me what's wrong about the existing definition).

See: https://techterms.com/definition/flag

In computer science, a flag is a value that acts as a signal for a function or process. The value of the flag is used to determine the next step of a program. Flags are often binary flags, which contain a boolean value (true or false). However, not all flags are binary, meaning they can store a range of values.

Let's start with:

a flag is a value

So apparently, according to this definition, a flag IS a value. So a flag can not be seen as something that be two different values (two different states).

The next sentence confirms that:

Flags are often binary flags, which contain a boolean value (true or false).

Let's say we have c++ std::bitset, but it's about 1 bit. Firstable, it's important to be aware of the difference between:

1. setting the flag
2. setting the bitset

The bitset can be 1 or 0  (in this case because we have one bit). If it's 1: it can be seen as set, if it's 0: it can not be seen as set. However, this should not be confused with setting the flag. A flag is a value. So the "bitset" (from above) set to 1, can be seen as a flag. And the bitset "set" to 0 (actually unset) can be seen as a flag. This is exactly what the definition above says:

Flags are often binary flags, which contain a boolean value (true or false).

So we have flags that contain the value true (1). And we have flags that contain the value false (0). So according to the definition above, one specific flag must NOT be seen as something that is 0 or 1. Let's say the bitset above is set to 1, then this is seen as a flag. If we would unset the bitset, then this must be seen as a different flag. So if we would see it like that, then actually a flag is just a predefined value that can be used to indicate something. Now let's take a look at the last part:

However, not all flags are binary, meaning they can store a range of values.

Now let's say we have a bitset that consists of two bits. Now we can make four different values:

00 = 0
01 = 1
10 = 2
11 = 3

So now they are saying that this non-binary flag can store a range of values (0-3). So now suddenly the flag is not seen as just a value, but the flag is seen as something that can store a range of values. So in their definition of a flag, they give two different definitions of a flag that contradict each other. So this definition is anyway incorrect and not useful.

Now let's take a look at another definition, see: https://whatis.techtarget.com/definition/flag

In programming, a flag is a predefined bit or bit sequence that holds a binary value. Typically, a program uses a flag to remember something or to leave a sign for another program. For example,  in a message being exchanged by two programs, a three-bit flag's field or data area might be set to one of three configurations:

Now first the term "binary value" is important. Let's take a look at the previous definition: https://techterms.com/definition/flag

However, not all flags are binary, meaning they can store a range of values.

In this case, "binary" is seen as 1 or 0 (true or false). But a "binary value" in the context above, we must see differently. See: https://en.wikipedia.org/wiki/Binary_number

In mathematics and digital electronics, a binary number is a number expressed in the base-2 numeral system or binary numeral system, which uses only two symbols: typically 0 (zero) and 1 (one).

So a binary number is just a number expressed in the base-2 numeral system. A binary number can be for example 11 (three). They must have meant it like that, because they are saying:

In programming, a flag is a predefined bit or bit sequence that holds a binary value.

If it was only about 0 and 1, then they could just say:

In programming, a flag is a predefined bit that holds a binary value.

So they must have meant it as something that can be different than only 0 or 1 (false or true). This is for example the mistake that @noci is making here: https://www.experts-exchange.com/questions/29122213/What-is-the-difference-between-mode-and-flag.html?anchorAnswerId=42711228#a42711228

(a question like "what is a binary value" gives me that impression as it's name literary mean 2 way value... customary we give that value 0, 1 )

It was about the same sentence. Now let's go back to our example with a bitset of two bits. We can make four different values (00 = 0, 01 = 1, 10 = 2, 11 = 3). Actually we can leave the word "binary" away, because all values consist of bits, because a computer is just one big sequence of bits. For example, the octal number system consists of bit sequences (each of 3 bits). So in the end, it's also about a bit sequence. So actually they are just saying:

A flag is something that holds a value.

So again, a flag is not something that can be for example: 0,1,2 or 3 but it's something that IS 0,1,2 or 3. However, now check this part of the definition:

For example, in a message being exchanged by two programs, a three-bit flag's field or data area might be set to one of three configurations:

001 (meaning "I'm a self-contained message")
011 (meaning "I'm one of several chunks of data in this message")
111 (meaning "I'm the last chunk of data in this message")

In this case, "set" refers to setting one or more bits, because it are the bits that are set. If none of the bits are set to 1, then you would have:

000

Then no bits are set, but this represents also a value. One specific bit can be set to only one value (1)...however, one bit represents two values (0 or 1, true or false). In this case, they are talking about:

a three-bit flag's field or data area might be set to one of three configurations:

So it might be SET to three different configurations/values. However, they can represent FOUR different configurations/values (000 too). So in the end, I would conclude this:

"A flag can be seen as a predefined value that can be used to indicate something. "

This correspondents with the definition just discussed. And this also explains why for example O_RDONLY, O_WRONLY et cetera are called flags:

For example, see: https://unix.superglobalmegacorp.com/Net2/newsrc/sys/fcntl.h.html


/*
 * File status flags: these are used by open(2), fcntl(2).
 * They are also used (indirectly) in the kernel file structure f_flags,
 * which is a superset of the open/fcntl flags.  Open flags and f_flags
 * are inter-convertible using OFLAGS(fflags) and FFLAGS(oflags).
 * Open/fcntl flags begin with O_; kernel-internal flags begin with F.
 */
/* open-only flags */
#define      O_RDONLY      0x0000            /* open for reading only */
#define      O_WRONLY      0x0001            /* open for writing only */
#define      O_RDWR            0x0002            /* open for reading and writing */
#define      O_ACCMODE      0x0003            /* mask for above modes */

For example, see: https://github.com/spotify/linux/blob/master/include/asm-generic/fcntl.h


/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
   located on an ext2 file system */
#define O_ACCMODE      00000003
#define O_RDONLY      00000000
#define O_WRONLY      00000001
#define O_RDWR            00000002

Now you're probably wondering, what's the question? Thw way I'm thinking here, is this correct? And if not, which part exactly is wrong? And why?
Avatar of Kyle Abrahams, PMP
Kyle Abrahams, PMP
Flag of United States of America image

To me:

A flag is something you check against, usually dealing with permissions.

EG:  
 HasAccess
 IsAdministrator
 CanChangeSettings

Flags that have multiple bit sets usually just represent other flags.  EG:
Chmod in unix - The permission set 777 means all people can read, write, and execute to it.  It's just a way of grouping it together for easier readability.


A Mode is a setting that controls one or more flags:
EG:

Mode              HasAccess                           IsAdministrator                    CanChangeSettings
Admin                      1                                                1                                                   1
ReadOnly                 1                                                0                                                   0
Writer                       1                                                0                                                   1
Anonymous             0                                                 0                                                  0


When dealing with file streams you have both the flag that is: CanWrite and also the mode which is open the stream for Writing, EG: The mode is I'm modifying the file, not just pulling information.
Avatar of Maarten Bruins
Maarten Bruins

ASKER

I'm not asking for general definitions, or your own definition, but specifically use the definitions in this post (and if necessary correct them and tell me what's wrong about the existing definition).

And my other question is about mode and flags. This question is specifically about flags.
A flag is a bit or set of bits that indicate something to be checked against.

In terms of Noci you're mincing words.

Let "bit" be defined as a single value of either 1 or 0
Let "word" be defined as 1 to N bits

The fact that a flag can be a word doesn't negate that the word is representing a number of bits.  At the end of the day the flag is something that needs to be compared against to determine whether you can do something or not.
Again a reminder:

I'm not asking for general definitions, or your own definition, but specifically use the definitions in this post (and if necessary correct them and tell me what's wrong about the existing definition).

Furthermore:

Let "bit" be defined as a single value of either 1 or 0
Let "word" be defined as 1 to N bits

True, but so?

The fact that a flag can be a word doesn't negate that the word is representing a number of bits.

Also true, but so?

In terms of Noci you're mincing words.

No explanation or what? It's about the term "binary value" in that context and I'm exactly saying why it can not be seen like that in that context. So then I would remind you to:

And if not, which part exactly is wrong? And why?
Well, I didn't read all the answers in your previous question and I don't really agree with that definition.
In the age of the dinosaurs, when programs were written in assembly, flags where bits indicating a condition. Like the carry flag, zero flag and so on. These flags were set or reset based on the result of an operation and were used in conditional jumps. The flags of a CPU are usually arranged as a bit field. Today we rarely consider the CPU flags (although they are still there) or use them explicitly.

So, basically, a flag is a value we can read and / or set, that indicates that a condition is met (or not).
Most of the flags are binary, because setting a flag is a simple OR operation, resetting a flag is an AND with the 1's complement, testing if it is set is again AND.

In fcntl.h, those values are normally called modes and not flags.
Is 101 a binary value?

But if that makes up 3 distinct values of  1 - 0 - 1 are they each their own binary value?

So what do you call a value of values?

What do you call the 0 of 101 if it's also a distinct flag?

We summarize them all to be values because that's what they are.  You're getting deep into the weeds for no reason.  The thing to keep in mind is the flag is meant to be checked against something.  Move on.
@Mihai:

So, basically, a flag is a value we can read and / or set, that indicates that a condition is met (or not).
I don't think that this is what a flag basically is, because you also have flags
Most of the flags are binary, because setting a flag is a simple OR operation, resetting a flag is an AND with the 1's complement, testing if it is set is again AND.

So this from my post:

For example,  in a message being exchanged by two programs, a three-bit flag's field or data area might be set to one of three configurations

So you're saying that's not a flag, because it's about setting three configurations instead of two?

In fcntl.h, those values are normally called modes and not flags.

What you mean by "normally", because see for example: http://man7.org/linux/man-pages/man2/open.2.html You see that everywhere, they are called flags.


@Kyle:

Is 101 a binary value?

yes.

But if that makes up 3 distinct values of  1 - 0 - 1 are they each their own binary value?

Yes.

What do you call the 0 of 101 if it's also a distinct flag?

It just depends on how it's used. The 0 in 101 could be used as a flag. You can see it as a predefined value, so yes. You can just use only one specific bit (that has a certain predefined value) in a bitset. Then it can be seen as a flag with the last definition discussed in my first post.

We summarize them all to be values because that's what they are.  You're getting deep into the weeds for no reason.  The thing to keep in mind is the flag is meant to be checked against something.  Move on.

Lol, so there is no good definition of something and then you're saying just move on. Probably everyone is doing this and that's why there are so many bad/incorrect definitions out there in the first place. So this is totally not the answer I'm asking for ;), but thanks anyway.
If you look at the man page, you will find:
The argument flags must include one of the following access modes: O_RDONLY, O_WRONLY, or O_RDWR.  These request opening the file read-only, write-only, or read/write, respectively.

That field is called flags because the other values are bits and are used the way I have previously described. O_ACCMODE is used to filter the opening modes from the other flags.
Okay, but for example see: https://github.com/spotify/linux/blob/master/include/asm-generic/fcntl.h


#define O_ACCMODE      00000003
#define O_RDONLY      00000000
#define O_WRONLY      00000001
#define O_RDWR            00000002
#ifndef O_CREAT
#define O_CREAT            00000100      /* not fcntl */

Then what exactly is the difference here between for example O_CREAT (which is called a flag on the man page) and O_WRONLY (which we would call for now a mode)?

In the end, both O_WRONLY and O_CREAT represent a value (00000001 and 00000100), so what's the difference?

00000001, 00000002 or 00000100 are all three just a value. The only difference I can think of, is that they are different values, but that's all. Or what else if the difference?
The difference is the way they are used:

Can I use the handle for writing?
The code would look like: if ((flags & O_ACCMODE) == O_WRONLY ||  (flags & O_ACCMODE) == O_RDWR) then I can write to it.

Should I create the file on open (if it does not exist)?
The code would like: if (flags & O_CREAT) then I should create the file.

Note that the values used for flags have only one bit set.

I, as a dinosaur, would refer to things as flags only when we are talking about boolean things.

Another thing to notice, in your example, is that the values you refer to are bit fields. O_CREAT is the representation of this flag in the context of the whole bit field.
@Mihai Thanks! I think we're making some steps :).

Can I use the handle for writing?
The code would look like: if ((flags & O_ACCMODE) == O_WRONLY ||  (flags & O_ACCMODE) == O_RDWR) then I can write to it.

But how I have to see this? In my previous post I said:

In the end, both O_WRONLY and O_CREAT represent a value (00000001 and 00000100), so what's the difference?

00000001, 00000002 or 00000100 are all three just a value.

Then why flags like O_CREAT are not just 0 or 1? Why they have a value of for example 00000100? And we also saw: "O_RDWR 00000002".  Let's say it's 2 to make it easier to follow. Now let's take a look at:

(flags & O_ACCMODE) == O_RDWR

How something that is 1 or 0 can be 2 (O_RDWR 00000002) in the end. So how I have to see this?

And about:

Should I create the file on open (if it does not exist)?
The code would like: if (flags & O_CREAT) then I should create the file.

O_CREAT is also a flag, so it's already part of the flags. So do you mean the following?

if (O_CREAT & other_than_creat_flags)

But before you were talking about a if-statement in the form of:

if( flags == something)

So how do you see that? And about:

Another thing to notice, in your example, is that the values you refer to are bit fields. O_CREAT is the representation of this flag in the context of the whole bit field.

Thanks for noticing! I don't know if I'm really aware of the exact difference between a bitset and a bit field, but in the end I see both of them as bit/bit sequences, so I think that's relevant here? But if it's important to see it differently, then just let me know.
Ok, bitsets and bit fields are more or less the same thing.
If you fill a bit field with flags, each flag must have its own, well defined, position. If this bit field has 16 bits and you look at this bit field as an integer, it will have a value that is not only 0 or 1.

In the example you gave, fcntl.h, all those O_ thingies have octal values. All numbers, that have only a 1, 2, 4 or 8 in them and the rest are 0's, are bit fields with only one bit set.

O_RDONLY, O_WRONLY and O_RDWR are modes (a flag definition cannot be 0), that is why the test construct is different.
How do you know that they are modes? Well, it's written in the man page, in the snippet I quoted earlier.
Thanks a lot Mihai! We're moving ;), we're on the right track I think.

If you fill a bit field with flags, each flag must have its own, well defined, position. If this bit field has 16 bits and you look at this bit field as an integer, it will have a value that is not only 0 or 1.

But I can say the same for bitsets. Let's say I have a bitset of three bits:

0: 0
1: 0
2: 1

If you look at it as a whole, then you can see it as the value 4. However, you can also just use the "last" bit, so then it's 0/1 so you can use it as a flag. This is already what I was saying when asking the question. So I don't really understand what you're trying to say with this, but for now first let's go further:

In the example you gave, fcntl.h, all those O_ thingies have octal values. All numbers, that have only a 1, 2, 4 or 8 in them and the rest are 0's, are bit fields with only one bit set.

O_WRONLY and O_CREAT both start with O_ so why we need to talk about this, because that doesn't show any difference between O_WRONLY and O_CREAT? And about:

In the example you gave, fcntl.h, all those O_ thingies have octal values. All numbers, that have only a 1, 2, 4 or 8 in them and the rest are 0's, are bit fields with only one bit set.

You're saying "all numbers", but to be more specific, you mean "all octal numbers"? For example 16 (base-10) = 000 010 000, so the base-10 number 16 has not only the number 1 in them, but also 6. But still...only one bit is set.
But for octal numbers you're right. For example: 040...it has only 1, 2, 4 or 8 in it and only then there is only one bit set.

To make it easier to follow, for now just let's see the octal system as a sequence of 3 bits, so we can make the values 0,1,2,3,4,5,6,7:

0 000
1 001
2 010
3 011
4 100
5 101
6 110
7 111

So what you're saying is that there is only one "1" when it's about the base-10 numbers 1,2,4. However, we can still make 8 different (0-7) values with this sequence. Are you actually saying that only octal numbers with only one bit set (not bitset, but a bit that is set) can be seen as a flag? And if yes, then why that bit must be part of the octal number? Why it can not be just be 0 or 1? And:

O_RDONLY, O_WRONLY and O_RDWR are modes (a flag definition cannot be 0),

But only O_RDONLY is 0, right? But I'm still struggling with:

a flag definition cannot be 0

Maybe the answer lies in the octal/sequence story, so then it will automtically become clear later on. Just some more questions to know how you see it. Can a flag consists of a bit sequence with two or more bits that are set? Or can a flag only consists of a sequence with only one bit that is set?

Now O_RDONLY, O_WRONLY and O_RDWR are defined as follows:

#define O_RDONLY      00000000
#define O_WRONLY      00000001
#define O_RDWR            00000002

What if they would be defined as:

#define O_RDONLY      00000001
#define O_WRONLY      00000002
#define O_RDWR            00000004

Then we could call them flags? And what if we would have:

#define O_RDONLY      00000001
#define O_WRONLY      00000002
#define O_RDWR            00000003

Then we could not call them flags?
Well, lots of confusion here, ehence you think the definitions are wrong when they are not.

First, a flag is a value, the type doesn't mater, it can be anything (even an object) as long as it is comparable.
All the samples given do just that: data comparision, the fact that they are 8 bits, 16 bits are only for historical reasons, and that's specific cases.
Plus, the fact that flags are often boolean is also a specific case.

Second, a bit is already holding a range of 2 possible values (0 or 1)., so assuming that 2 bits is a range of values while 1 bit is not, is wrong to begin with.

Third, a bitset is a container that hold bit elements.
You set an element, but surelly you don't set the container.

Fourth, do not confuse binary with boolean, as everything in computer science is binary, but not everything is boolean.
First, a flag is a value, the type doesn't mater, it can be anything (even an object) as long as it is comparable.
All the samples given do just that: data comparision, the fact that they are 8 bits, 16 bits are only for historical reasons, and that's specific cases.
Plus, the fact that flags are often boolean is also a specific case.

100% agree and exactly the same as what I'm saying in my first post.

Second, a bit is already holding a range of 2 possible values (0 or 1).

Agree.

so assuming that 2 bits is a range of values while 1 bit is not, is wrong to begin with.

Where do you see me making this assumption? I see 2 bits indeed as a range of values (each value 0 or 1). And in some way I also see 1 bit as a range of two values (0 or 1).

Third, a bitset is a container that hold bit elements.
You set an element, but surelly you don't set the container.

Agree and I'm thinking the same.

Fourth, do not confuse binary with boolean, as everything in computer science is binary, but not everything is boolean.

Agree, and also do not confuse "binary" with "binary number". You can see a computer as binary (0 or 1), but a binary number doesn't have to be only 0 or 1.

So actually we're saying pretty much the same, except the "assumption" part, so maybe that's why I think the definition is incorrect and you think it's correct. So let me know where you see me making that assumption?

To be sure, I'll repeat why in my opinion e.g. this definition is incorrect:

In computer science, a flag is a value that acts as a signal for a function or process. The value of the flag is used to determine the next step of a program. Flags are often binary flags, which contain a boolean value (true or false). However, not all flags are binary, meaning they can store a range of values.

So what they are saying first:

flag = value

And then they are saying: "a flag stores a value". So put flag=value in that sentence and you will have:

a value stores a value

A value can consist of a value. For example, let's see the value 3 as 11 (binary). Then in some way the value 3 consists of two values, two 1's. However, how a value has to store a value?

P.S. By the way, I'm not saying that the second definition discussed in my first post is incorrect.
You're saying "all numbers", but to be more specific, you mean "all octal numbers"?
Yes.

Look at it this way: O_CREAT is a 1 bit flag, what you see in the header file is this flag in the context of the bitset int flags. Or to be more specific, is the mask to select this flag from int flags (in the context of int open(const char *pathname, int flags);)
As I have said earlier, you can operate with this flag using bit-wise operations on int flags. The int in this case is actually a bitset, not an int as in the number of candies I have eaten.

If you have the flag defined as 000000000 what can you select with this mask?
And then they are saying: "a flag stores a value". So put flag=value in that sentence and you will have:
If you really want to be precise:
A flag is something with a value semantic that store a value.
But that's playing with words ....
You can see a computer as binary (0 or 1), but a binary number doesn't have to be only 0 or 1.
I shoudl have said that computers represent everything as binary.
No mater the number, it can be represented in various form.
Take the number 12 as a sample:
Decimal (base 10): 12.
Roman: XII
Octal (base 8): 14
Hexadecimal (base 16): C
D'ni: User generated imageBinary (base 2): 1100

Most of the time, humans use the Decimal system.
Computers always use the Binary system.
Whatever the representation, the value is the same for a given number.
@Mihai:

You're saying "all numbers", but to be more specific, you mean "all octal numbers"?
Yes.

Thanks, but I also had some other questions in the same post. We can try to skip them, but maybe it's good to get those questions clear first, before we're going to the next step. I think it will take much longer if we're not doing it step by step. But okay, first let's try it your way to see if you can make clear what you mean. I'll just share my thoughts on what you're saying so you can see where I'm losing you with what you're trying to tell me.

Look at it this way: O_CREAT is a 1 bit flag

I think you're already going to fast now, because I'm not there yet. We have:

#define O_CREAT            00000100

If this is an octal number, then it represents the base-10 number 4. So there is more than one bit involved. Only 1 is set, but the other non-set bits are also important otherwise you would never get 4. So it's fine for me to see this as a flag, but with this flag are multiple bits involved, however one is set. Then I'm already thinking, for what we need the other bits? They are 0 anyway, otherwise we can not "make" the base-10 number 4.

what you see in the header file is this flag in the context of the bitset int flags.

What I see is the base-10 number 4 described in octal-way. So let's do it step by step. To make it easier to understand, only let's take a look at the base-10 numbers 0-7. So we need three bits, right? So the base-10 number 4, consists of 3 bits when denoted in octal-way (100)? If a flag is a value, do you see the value 4 (100) as the value, or do you see the "1" in 100 as the value? (the value that is the flag)

Or to be more specific, is the mask to select this flag from int flags

Here I lost you, because you skipped some steps. So first we have to discuss the things above.

If you have the flag defined as 000000000 what can you select with this mask?

Okay as an example, imagine a 1 bit flag. A bit is 0 or 1. These are just two values. So for me there is no difference between 0 and 1. I can say 1=yes, 0=no. However, I can also say 1=no, 0=yes. I see them as they are exchangeable. So 0,1,2,3 or whatever, I just see as a value. So 000000000 is a value and 000000001 is also a value. Both can say something about something. Let's say if I'm wearing black shoes, we use:

000000000

And if we use red shoes, we can use:

000000001

However, we can also just turn it around. I would love to see it on your way, but the problem is that I don't see yet what you mean. It's not that I want to stuck on my own thoughts, but I really don't see what you mean so probably we really need to take it step by step.

@Fabrice: I didn't read your post yet, so that's what I'm going to do now.
@Maarten: have a look at bitwise operations.

The key to what I have said is
The int flags in this case is actually a bitset, not an int as in the number of candies I have eaten.
The values you see in the header file are masks for bitwise operations. Their values are meaningless per se, all that matters is that they select a certain bit from a bitset.
@Fabrice:

If you really want to be precise:
A flag is something with a value semantic that store a value.
But that's playing with words ....

No, it's not playing with words. For me it's important for understanding it correctly in the first place. I'll tell you why it's important. Let's say we have two flags. Flag A and Flag B. As an example, we can see it in two different ways:

1. If flag A can store a value, then flag A can contain the value 0 at time X. And at time Y, flag A can contain the value 1 (after "storing" the value 1).

2. If flag B is a value, then it has OR value 0 OR value 1.

That's what makes it important. We need to see it as way 2, right? But then it's not just playing with words, because it makes a big difference as you can see.

I shoudl have said that computers represent everything as binary.

But I agree, a computer are just 0's and 1's. I think so far you said exactly the same things that I said in my first post.
@Mihai: Thanks again! We're making some progress ;) (I think/hope).

Let's say "int flags" are three flags. And let's say we have a sequence of three bits (let's call this the bitset in this case). So now we start with:

0 0 0

Let's say:

0 0 1 => represents me wearing black shoes
0 0 0 => represents me wearing white shoes

0 1 0 => represents me wearing black shirt
0 0 0 => represents me wearing white shirt

1 0 0 => represents me wearing black pants
0 0 0 => represents me wearing white pants

1 1 1 => represents me wearing black shoes, shirt, pants
1 0 1 => represents me wearing black shoes, pants but a white shirt
0 0 0 => represents me wearing white shoes, shirt, pants

Do you mean it like that? But then the value 0 also says something, we can just turn around black and white. If this is correct, what exactly in this example would you call a flag?
Almost.

Here we have
  • the rightmost bit is the shoe flag: mask 001 (binary and octal)
  • the middle bit is the shirt flag: mask 010 (binary, octal 002)
  • the leftmost bit is the pants flag: mask 100 (binary, octal 004)

Indeed the value 0 of the bitset says something, but a mask with value 0 is absolutely useless
the rightmost bit is the shoe flag: mask 001 (binary and octal)
the middle bit is the shirt flag: mask 010 (binary, octal 002)
the leftmost bit is the pants flag: mask 100 (binary, octal 004)

Okay and how you would describe black shoes/shirts/pants? Like below?

mask 111 binary, octal 007
Nope. That's the bitset.

#define O_SHOE  001
#define O_SHIRT  002
#define O_PANTS 004

dressed = O_SHOE | O_SHIRT | O_PANTS (black / black / black) :)

Make shoes white:
dressed &= ~O_SHOE

Is the shirt black:
isShirtBlack = dressed & O_SHIRT

And so on...

The flag is the bit from the bitset. For each flag there is one mask and, as you can see, you need 3 masks to express the 8 possible situations.
@Mihai: Thanks a lot again! If you would have said "yes" then I would not understand it anymore, but now we can go further with the next step. To be sure:

dressed = O_SHOE | O_SHIRT | O_PANTS (black / black / black) :)

To be sure and to avoid confusion, do I have to see "|" as OR here? Because if that's the case, then it's only possible to use "dressed" to indicate the color of one of the three parts (shoes, shirts, pants). Is this correct or do you mean it differently?

In other words, can you also make the shoes and the shirt white at the same time? I'm working to something, but before I want to have some things clear ;).
You are focusing too much on bits, and I say it again: Bits are a particular case in the concept of flags.

Compare 2 values, if they're equal, the flag is set, else it is not.

Now in the particular case of bits:
The smallest value computers can handle are 8 bits, in other words: char data type.
And it is possible to store something that have more than one meaning (all that is up to the developer), in the case of char data type: up to 8 boolean things.
You have a variable and you want to check a single bit, you need to mask the variable to isolate the single bit.
You do a comparition of the result of a  mask operation (in fact, a bitwise AND operation), if the interresting bit set, the result of the comparition will be the mask), else it is zero.

To take your sample, a check if you're wearing a black shirt can be done by the following:
const int BLACKSHIRT_MASK = 002;
// const int BLACKSHIRT_MASK = 2;       // same as above
// const int BLACKSHIRT_MASK = 0x02;    // same as above

int result = flags & BLACKSHIRT_MASK;
if(result == BLACKSHIRT_MASK)
    std::cout << "You're wearing a black shirt."
else
    std::cout << "You're wearing a white shirt." 

Open in new window

To be sure and to avoid confusion, do I have to see "|" as OR here?
Erm ...
Check back your C++ syntax....
Yes, that's on OR operator.
But here is where you are wrong. The dressed thingy is a bitset (let's assume an int), not a flag (a bit).
So (binary):
bitset (int) dressed = 001 | 010 | 100 = 111 (or 007 octal)

Open in new window

@Fabrice:

To be sure and to avoid confusion, do I have to see "|" as OR here?
Erm ...
Check back your C++ syntax....

This is not about the C++ syntax, this is about something what Mihai was saying to me (in the end it can be about the C++ syntax but that's a difference). I wanted to be sure we're talking about the same stuff. Often I'm talking with people who are just using their own way of writing things down. So it's not that weird to ask this to be sure.

P.S. The post before of you is useful (thanks!), but I'm still thinking of it, so I'll come back to it later on.


@Mihai: Thanks a lot again! I think we're almost there.

But here is where you are wrong. The dressed thingy is a bitset (let's assume an int), not a flag (a bit).
So (binary):
bitset (int) dressed = 001 | 010 | 100 = 111 (or 007 octal)

It's good you're writing it down like that, because now I can say exactly what my problem is about it:

1. dressed = 001 | 010 | 100
2. dressed = 001 OR 010 OR 100
3. Let's say it's 001, so: dressed = 001
4. Now we have dressed = 001 = 111

And it's not possible that 001 is equal two 111. But maybe I already understand what you mean, but before I'm going to write a whole story, maybe first you can answer this question:

In other words, can you also make the shoes and the shirt white at the same time?

Is this possible in your "story"?
Aaaaa, your logic is wrong.

The | is the bitwise OR operator.
001 | 010 = 011
It's not the logical OR operator, that is  ||.
Review the link I have sent you before.
1. dressed = 001 | 010 | 100
2. dressed = 001 OR 010 OR 100
3. Let's say it's 001, so: dressed = 001
4. Now we have dressed = 001 = 111
Expressions 1 and 2 assign the 111 value to dressed.
The 3rd assign 001 to dressed.
The 4th is a no sens, since a variable can hold only one value at a given time.
@Mihai: Ah so it's good I've asked ;). That explains a lot. I have a PHP/CSS/HTML/JAVASCRIPT/MYSQL background so when I see "|" I'm not immediately thinking of a "bitwise OR". I just started to read the post of Fabrice (https://www.experts-exchange.com/questions/29123023/What-is-the-definition-of-a-flag.html?anchorAnswerId=42715067#a42715067) and then I already started to think that maybe the problem lies there.

I thought you just meant OR with | (sorry for misunderstanding). But thanks a lot for making this clear to me (and the patience to find the problem)! Soon I have to stop working and coming week I have less time, but I'll come back to this topic. I'll read some more about the "bitwise OR" and then I'm going to read the posts again. And eventuelly, I can take a look at the definition of "flag" again.

Fabrice and Mihai: already thanks a lot!! Really appriciate it!
one remark about bits and integers represented with a different base

    #define O_CREAT            00000100


If this is an octal number, then it represents the base-10 number 4. So there is more than one bit involved.

the base-10 number 4 has exactly 1 bit (the third bit at bit position 2 from right) set to 1 and all other bits are zero.

note, all multiples of 2  (binary: 10) regardless which base (2, 8, 10, 16) is used will have exactly  1 bit set:

binary 0     == octal 000000 == decimal 0   == hex 0x0 
binary 1     == octal 000001 == decimal 1   == hex 0x1    == 2^0
binary 10    == octal 000002 == decimal 2   == hex 0x2    == 2^1
binary 100   == octal 000002 == decimal 4   == hex 0x4    == 2^2
binary 1000  == octal 000010 == decimal 8   == hex 0x8    == 2^3
binary 10000 == octal 000020 == decimal 16  == hex 0x10   == 2^4
binary 01111 == octal 000017 == decimal 15  == hex 0xf    == 2^4 - 1

Open in new window

[/code]

you see that any binary number which is a power of 2 would make a bit-shift by 1 to the left if the previous power of 2 was doubled.

that is because a binary number which represents 2^n - 1 exactly has all bits from 0 to n-1 set to 1.

mathematically we therefore have 2^n == 2^(n-1)+1.

you also see that the binary number 0 is not a bit flag itself because you can't set it. of course it is a bit value and you can give this value a meaning, e. g. false.  but the main meaning is always that it negates the bit flag which has the value 1.

with ~x you toggle all 1's of a bit container x.

so if you do

   byte x = O_WRONLY;  // ab byte has 8 bits an x == 00000001 binary
   int y = ~x;   // turns all 1's to 0 and 0's to 1   y = 11111110 binary

Open in new window


the main point of this that by using the negate operator ~ you made that O_WRITE is no longer set

 z = (y & O_WRONLY);  

Open in new window


would result in z == 0.

that is because the bitwise & compares bits at the same bit position. if they are different the result bit is 0. otherwise 1.

x 00000001
y 11111110
-----------------
z 00000000

z therefore means that O_WRONLY which was assigned to x is no longer set in y. in other words O_WRONLY is false in the bit sequence of x.

you can do the same with all other bit flags beside of O_RDONLY. since O_RDONLY == 0 you can "set" it by assigning it to a bit container of arbitrary length. but when you this, the result is not different to the default initialization which is also 0 (all bits are 0). and the negation of O_WRONLY is 0 what would mean that the negation of O_WRONLY flag menas that the flags turns to O_RDONLY. that conclusion obviously is wron, if the 2nd bit is set by OR'ing O_RDWR.

byte x = O_WRONLY;  // set x to 1
byte y = ~O_WRONLY & O_RDWR;   // sets y to 2  (or 10 binary)
byte z = y | O_RDONLY;    // we try to set O_RDONLY flag additionally to O_RDWR
if ((z & O_RDONLY) != 0)
      std::cout << "flag O_RDONLY is set " << std::endl;
else
      std::cout << "flag O_RDONLY is notset " << std::endl;

if ((z & O_RDONLY) != 0)
      std::cout << "flag O_RDWR is set " << std::endl;
else
      std::cout << "flag O_RDWR is not set " << std::endl;

Open in new window


the output is that O_RDONLY is not set because 0 is not a power of 2 (not a valid bitflag).

note, if you have a bit sequence of length n, each value from 0 to 2n-1 can be built with this sequence. and the 0 is a valid value but the 0 is not a valid bitflag of this bit sequence.

Sara
I'm back ;) (it will be a long post, but I think it's necessary to get things clear). I've read everything again and now I understand some things some more how they are meant. However, I still see some inconsistencies between what different people are saying when it's about this question. I'll walk through everything and I'll write down my thoughts, so you can correct me if you think I have to see something differently.

Let's start with some basics. First let's interpret the following:

a flag is set

A variable can be set (variable exists) or a variable can be unset (variable does not exist). So the same we I see it with flags. A flag can be set (flag exists) or a flag can be unset (flag does not exist).

In this post, I'll only take a look at bitset of two bits (to make it easier to follow).

Decimal:  Binary:  Octal:
0         00       0
1         01       1
2         10       2
3         11       3

Open in new window


Furthermore, some definitions that we'll possibly use:

&  = bitwise c++ AND operator
|  = bitwise c++ OR operator
|| = or

Open in new window


First the question is, what exactly is called a flag? Things like:

#define O_CREAT		00000100 (binary: 1000000, decimal: 64)
#define O_EXCL		00000200 (binary: 10000000, decimal: 128)

Open in new window


So in our example (two bits), let's see this as:

#define O_CREAT		01
#define O_EXCL		10

Open in new window


So we can see "01" as a flag. And we can see "10" as a different flag. However, the flag doesn't always exist, because they are in between:

#ifndef O_VAR
#define O_VAR
#endif

Open in new window


This is not the case with for example:

#define O_ACCMODE	00000003
#define O_RDONLY	00000000
#define O_WRONLY	00000001
#define O_RDWR		00000002

Open in new window


I think, exectly this is the reason why these can not be called a flag. A flag must be something that sometimes exists, but sometimes it shouldn't exist. That's why I think it's incorrect to call a flag a "predefined value". It's a value that will be "created" depending on the situation. That's something different than a "predefined value", because a "predefined value" is always there, but a specific flag can exist OR can not exist. Some people here were saying that it's because O_RDONLY is 0, but that's not the reason I think.

Now let's take a look at: http://man7.org/linux/man-pages/man2/open.2.html

int open(const char *pathname, int flags);

So with "int flags" you're actually saying: by default no flags exist at all, but by mentioning a flag, the flag will be created. So only from that moment, one or more flags exists. Before a flag is not a flag yet.

Let's say a flag is "created" and let's see it as "01". Now this flag can be used to compare it against something (or to compare something against the flag, it's just how you look at it).

01 (flag) & something == 01 (flag)       => now we know the flag is set (flag exists)
01 (flag) & something != 01 (flag)       => now we know the flag is not set (flag doesn't exists)

Open in new window


This is one way to look at it. If you see it like that, then some people are saying that it's useless to have a flag that consists of "00" (compare it with O_RDONLY 00000000).

00 & something == 00       => that's always 00 in the end, independent of what "something" is

But I don't know yet whether or not I agree with that. If you see it like that, then in some way you can see "00" as a flag, because you can compare it with "00" (something) and then you know the flag "00" exists. So that's my first "problem" that I'm struggling with.

But if we have to see that "something" as something that must have the ability to be compared with DIFFERENT flags, then "00" can not be seen as a flag. Because then we will have:

00 & 00 == 00       => flag 00 exist

Open in new window


01 (flag) & 00 == 00       => flag 01 doesn't exist

Open in new window


So then it's never possible to check whether or not another flag exists, because in this case "01" actually exists, but we can not detect this with our method. So the question whether or not "00" can be seen as a flag comes down to to what the flag will be compared against. So what is "something"? How we have to see that "something" exactly?

In my first post, I started with this definition:

In computer science, a flag is a value that acts as a signal for a function or process. The value of the flag is used to determine the next step of a program. Flags are often binary flags, which contain a boolean value (true or false). However, not all flags are binary, meaning they can store a range of values.

Now let's zoom in on this part:

Flags are often binary flags, which contain a boolean value (true or false).

At least I think this is misleading. A flag contains one or more boolean values, right? Not only always "a" boolean value. For example, let's go back to our example flag "01". One bit is set, but the flag consists of two bits, so it consists of two times true or false (two times 0 or 1).

However, not all flags are binary, meaning they can store a range of values.

How I have to intrepet this sentence now? Anyway a flag consists of values and doesn't store them. A flag "is" the "values". It's not that we have a flag "01", and that flag stores something in the empty bit, and then the same flag is suddenly "11".

But how exactly I have to see the range of values? Do I have to see it as a "bit" (let's call it box because a bit is only 0 and 1) that suddenly can contain not only 0 or 1, but also for example 2?

So instead of having two flags: 01 and 10, now we can just use one box with 1 and 2? Or what do they mean this:

However, not all flags are binary, meaning they can store a range of values.

As we saw, a flag can be an octal number. However, in the end it's just a row of bits with only one bit that is set. So is this still called a "binary" flag? Or it's not seen as a "binary" flag because the flag is an octal number?
And what exactly do they mean with a range of values?

Now let's take a look at the second definition:

In programming, a flag is a predefined bit or bit sequence that holds a binary value. Typically, a program uses a flag to remember something or to leave a sign for another program. For example, in a message being exchanged by two programs, a three-bit flag's field or data area might be set to one of three configurations:

001 (meaning "I'm a self-contained message")
011 (meaning "I'm one of several chunks of data in this message")
111 (meaning "I'm the last chunk of data in this message")

I still don't understand this:

a three-bit flag's field or data area might be set to one of three configurations

I would see this totally different. Let's say:

001: send part 1 of message
010: send part 2 of message
100: send part 3 of message

They are talking about the "flag's field", so the field ot the flag, but this is not the flag? We just have three different flags here. We can combine different flags, to accomplish different things. Let's say we want to send a message that only contains part 1 and part 2, but not part 3. Then we will set the first two flags (001 and 010). In some way we can combine the two flags to one:

001 | 010 = 011

But the 011 we can not call a flag, right? We can call 001 and 010 a flag, but not 011. Will "001" and "101" be separately compared with that "something" from earlier in my post? Or will "011" be compared with that "something" from earlier in my post? So about:

a three-bit flag's field or data area might be set to one of three configurations

Three configurations? We just have three flags. We can use one flag to send the first part of the message. We can use the second for the second part, and we can use the third flag for the second part. And we can combine them (so not only three configurations). So actually this definition defines a flag and then starts to talk about an example that is about three flags?

@Mihai: You said:

So, basically, a flag is a value we can read and / or set, that indicates that a condition is met (or not).

I know it's about words (but with good definitions it's mostly about words), but I don't like to say it like that, because you're saying:

"a flag is a value we can set"

But in my opinion, we really have to say:

"a flag is a value when it is set"

In my opinion, that's a big difference. A flag is not a value, but it's a value is some specific cases (but just correct me if I'm wrong). And if it's not like that, then apparently I still don't understand it for 100%. Furthermore, you also said this:

O_ACCMODE is used to filter the opening modes from the other flags.

The code would look like: if ((flags & O_ACCMODE) == O_WRONLY ||  (flags & O_ACCMODE) == O_RDWR) then I can write to it.

I don't understand this, because:

#define O_ACCMODE     00000003 (binary: 11)
#define O_RDONLY      00000000 (binary: 00)
#define O_WRONLY      00000001 (binary: 01)
#define O_RDWR        00000002 (binary: 10)

This is what you're saying:

flags & O_ACCMODE == O_WRONLY
flags & 11 == 01

flags & O_ACCMODE == O_RDWR
flags & 11 == 10

My first question about this: are you calling O_WRONLY and O_RDWR here flags? And how you're seeing "flags" here. Let's say we have two flags "01" and "10". Do you mean:

( 01 | 10 ) & O_ACCMODE == O_RDWR

But this can not be correct, so probably you mean:

01 & O_ACCMODE (11) == O_WRONLY (01)
10 & O_ACCMODE (11) == O_RDWR (10)
00 & O_ACCMODE (11) == O_RDONLY (00)

So as I said before, if we see it like that then "00" can be seen as a flag. However, should it be possible for a specific flag to exist or not exist? (by definition) Because e.g. O_WRONLY is just a predefined value. It's always there, so it can not be unset. So if we call O_WRONLY a flag, then a flag is always there, so it can not be set/unset because it's always set, it's just that value. With the other ones it's different, because it's:

#ifndef O_VAR
#define O_VAR
#endif

@Mihai: You also said this:
The code would like: if (flags & O_CREAT) then I should create the file.

How you can say this? How I have to see it? Because a flag is compared against something, a flag is not compared against another flag. O_CREAT is a flag, so with "flags & O_CREAT" you're actually comparing a flag with another flag?


@Fabrice:

const int BLACKSHIRT_MASK = 002;
// const int BLACKSHIRT_MASK = 2;       // same as above
// const int BLACKSHIRT_MASK = 0x02;    // same as above

int result = flags & BLACKSHIRT_MASK;
if(result == BLACKSHIRT_MASK)
    std::cout << "You're wearing a black shirt."
else
    std::cout << "You're wearing a white shirt." 

Open in new window


Thanks for this example, it was helpful in some way, but in the end it's about something like:

#ifndef O_VAR
#define O_VAR
#endif

Open in new window


And O_VAR is called a flag right? So something is defined and later on that will be compared against "something". Let's say the flag is "01" and it will be compared against "11". Then it's:

flag (01) & something (11) == 01 (is same as the flag)     => I'm wearing a black shirt

But you're saying:

if(flags & BLACKSHIRT_MASK == BLACKSHIRT_MASK)

However, I would see it as:

if(flag & something == flag)

That's the part what I don't understand about your example.

 A variable can be set (variable exists) or a variable can be unset (variable does not exist).
Nope, a variable is set (it hold a value different than zero), or a variable is not set (it hold a zero value).
Variable existances can't be erased, no mater the language.

A flag can be set (flag exists) or a flag can be unset (flag does not exist).
See my comment about variables, since flags are variables.
&  = bitwise c++ & operator
Bitwise AND operator
|  = bitwise c++ | operator
Bitwise OR operator.
#ifndef O_VAR
#define O_VAR
#endif

Open in new window

These are C and C++ features to prevent defining multiple time the same content, also known as "Include guards".
They are nowhere realted to flags.

Concerning everything else in your post:
Flags existance are not the question, a flag (like any variable) must exist before beeing tested, else the source code won't compile, the compiler will throw a bunch of insults (erm .. errors) at your face
So debating about flags existance is just a no-sens.
A flag is set (any non zero value) or unset (zero value) to indicate something, usually in the form of boolean.
that it's useless to have a flag that consists of "00"
This is not useless, this is a no-sens.
1:01 (flag) & 00 == 00       => flag 01 doesn't exist
Your comparision are also no-sens. Compare the flag with something, if the result is equal to the flag, then the flag is set.
1:01 (flag) & 00 == 01 (flag)       => flag 01 is set

Open in new window

A flag contains one or more boolean values, right?
Nope, boolean value are just a particular use case. You can check against any value, the result must be true or false:
std::string name
if(name == "Washington")    => the flag Washington is set

Open in new window

But how exactly I have to see the range of values?
Anything between a minimum and a maximum.
I still don't understand this:
Of course, since you make an essay from a very simple and trivial concept.
Return to the basis:
A flag is a variable checked against a value to make a decision.
Nothing else to add, nothing else to discuss.

(I gave up reading after this).
Thanks a lot Fabrice!

Nope, a variable is set (it hold a value different than zero), or a variable is not set (it hold a zero value).
Variable existances can't be erased, no mater the language.

Thanks! You're right, see:

<?php
$test = 'bla';

if( isset( $test ) ) {
	echo 'set/';
} else {
	echo 'unset/';
}

unset($test);

if( isset( $test ) ) {
	echo 'set/';
} else {
	echo 'unset/';
}

if( $test == 0 ) {
	echo '0/';	
} else {
	echo 'not 0/';
}

echo gettype($test) . '/';

$test = 0;

echo gettype($test) . '/';

if( isset( $test ) ) {
	echo 'set/';
} else {
	echo 'unset/';
}

?>

Open in new window


Output: set/unset/0/NULL/integer/set/. I was not aware of it. So that already changes some things. So when we have something like:

unset($test);

Open in new window


to be sure, after unsetting $test, $test can not be seen as $test having a VALUE (0), right? Because the term "value" only refers to $test being not NULL, right?

And about:

#ifndef O_VAR
#define O_VAR
#endif

Open in new window


You're also right about this (I was thinking the wrong way about it, was a bit stupid of me ;), tunnel vision) and that means that some things in my post were inaccurate.

But these are really important questions when it's about the definition of a flag, because first let's compare the term "flag" with the term "variable". Think like this:

1. $test is a variable
2. $test being 'bla' is not a variable. However, it's a variable $test that has been set to a specific value.

So now we have some different possibilities how to see the "flag". We can see it as:

- variable, or
- variable that has been set to a specific value, or
- the value 'bla'

OR

- a variable that can only be set to one specific value

So now let's go back to for example:

#define O_CREAT		00000100 (binary: 1000000, decimal: 64)

Open in new window


First let's take a look at it from one direction: We can not say that this is the flag. This is the flag O_CREAT that has been set. So that's the first step we have to make. So calling this line of code the flag is wrong. If we unset the flag O_CREAT, it's still the same flag. In other words, the flag still exists.

So if that's true then a flag is not a predefined value, because the flag can be:

a predefine value, OR!!!
NULL

If this is NOT correct and we have to see it differently, then we can not talk about an unset flag, because then it would not be a flag anymore anyway. So my question is, will they later on unset O_CREAT on some moments? Or will it always have a value? (in other words, not NULL)

For now, let's start with this, because this is why I got confused by the term "flag" in the first place. So how I have to see the flag? Because if I have to see it as:

a predefine value, OR!!!
NULL

Then actually we have to see the flag as something like:

a variable that can only be set to one specific value

So then it's not a predefined value, because the variable can also be NULL (no value). Then a flag can also not be called a value. Or we have to see "flag" as a predefined value (excluding NULL), but then you can not talk about an unset flag, because then unset means that's it's not a flag anymore.

We can talk about unsetting a variable, because a variable like for example $test is still a variable after unsetting it, but it just doesn't have a value. If a flag must be seen as a predefined variable, then we can not see it like that (as with a variable).

Let's first start with this step, before we're going further. I really have to do it step by step otherwise there are already too many assumptions. First I need to know what (which part) exactly is called "flag".

P.S. Meanwhile I'm going further with the rest of your post, but I already noticed that I was very sloppy in the post of mine you were responding to. I wrote things completely the wrong way and not how I wanted to say them. Sorry for that. I rewrote my post a couple of times, but I forgot to change some things.
I'll already go further with your post, so I'll edit this post here piece by piece.

1:01 (flag) & 00 == 00       => flag 01 doesn't exist
Your comparision are also no-sens. Compare the flag with something, if the result is equal to the flag, then the flag is set.
1:01 (flag) & 00 == 01 (flag)       => flag 01 is set

Sorry, I was really sloppy in my post I noticed. I meant it like this:

00 & 00 == 00       => flag 00 exist/set
01 & 00 == 01       => flag 01 exist/set

So if that "something" is "00" then every flag would give a match, so that's makes the comparison useless. Then you're making a comparison with something while in advance you already know the outcome is a match. So maybe this exactly explains why "00" as a flag will not work?

00 & 00 == 00       => flag 00 exist/set

This works, but if you have to check different flags against the same "something" (00), then it's useless because in all cases, the if-statement will be true anyway. So when it's about flags, is it never only about 1 flag? There are always more flags involved? Zero (or one, or more) flags can be set (exist depending on my previous post), but it's never just about one flag? Because otherwise maybe somehow "00" could be seen as a flag.


And about:

A flag contains one or more boolean values, right?
Nope, boolean value are just a particular use case. You can check against any value, the result must be true or false:

Probably my bad that I was not clear enough, but this was specifically about, see: https://techterms.com/definition/flag

In computer science, a flag is a value that acts as a signal for a function or process. The value of the flag is used to determine the next step of a program. Flags are often binary flags, which contain a boolean value (true or false). However, not all flags are binary, meaning they can store a range of values.

Before I said: "A flag contains one or more boolean values, right?". I quoted that bold part above it, but I had to say it more clear. So again and now good:

A binary flag (see quote) contains one or more boolean values, right? Because the quote is talking about only just "a" boolean value (true or false). But in the end, this comes down to the same question as in my previous post. What exactly do they mean by a boolean value (true or false)? Can I see that as a bit being 0 or 1? Or do I have to see it totally different? Now I realize that NULL maybe must not be seen as a value, then we can see the 0 in a bit also not as a value? Then a bit can not be seen as two values (value_0 OR value_1). Then we have to see value_0 as NULL (instead of value 0) and value_1 as value 1. So then a bit is not about two values, then a bit is about one value? How exactly I have to see this? I know it's only about words and terminlogy, but this is important to understand other stuff when such things become important.

And:

Of course, since you make an essay from a very simple and trivial concept.
Return to the basis:
A flag is a variable checked against a value to make a decision.
Nothing else to add, nothing else to discuss.

(I gave up reading after this).

I can understand you stopped after a while with that post. I know that somewhere something is not 100% right (can be just a small detail, or definition of something small), but I don't know yet what exactly. That's why everything became a bit chaotic. I have a bit strange brain ;), if some small detail is not correct, then my brain refuses to let the information in (or to remember it). However, in my previous post (https://www.experts-exchange.com/questions/29123023/What-is-the-definition-of-a-flag.html?anchorAnswerId=42716262#a42716262) I think I'm coming close to the "problem" by brain has with it. And I know probably many people think: if it takes you so much time to understand something "simple" as a flag, then you can better stop ;). But I know my brain already some longer, so everything will cost some more time on the beginning, but later on it gives advantage.
I really appricate your help so far and that you survived the "frustrations" while reading my posts. You still managed to respond really accurate on the things what I'm saying (instead of posting general things, so compliments).

So now it's actually only about my previous post and what exactly (which part exactly) is called "flag" (if I didn't make you too tired/if you still have energy for it).
hat exactly is called a flag? Things like:

#define O_CREAT            00000100 (binary: 1000000, decimal: 64)

O_CREAT is not a flag. O_CREAT is a constant with value hex 4 or decimal 4 or octal 4 or binary 100.

the binary value (which has only 1 bit set and all others are zero) tells that the constant can be used to check the 3rd bit of a bit container whether the 3rd bit is set or unset.

so the flag is the 3rd bit of a bit container (or bit set) with a size of at least 3 bits.

if we have a byte (== unsigned integer with 8 bits) this byte can be used as a bit container for 8 bit flags.

and we can use one-bit constants 2^0, 2^1, 2^2,.... (decimal 1, 2, 4, 8, 16, 32, 64, 128  or binary 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000) to check which of the 8 bit flags of the container is set and which is not. a bit flag is one bit of a bit container at a defined bit position. the bit position is a number in the range 0 and n-1  where n is the number of bits the bit container has.

so we have a difference between flag and bit flag. while the first (normally) is a boolean variable which is either true (1) or false (0), we have bit flags which would turn to normal flags if we extract the one bit at the defined bit position (e. g. the 3rd bit if we want to test against O_CREAT) and assign this single bit (with value 0 or 1) to a boolean variable.



note, obviously a 1 bit flag has 2 values true and false. if we call a bit sequence of 2 or more bits a flag we have some differences to a single bit flag.

  • it has up to 2^n-1 potential values where n is the number of bits
  • the valid flag values can be an enumeration 1,2,3,4,... for example colours 1=red, 2=green, ....
  • or they can be contiguous one-bit constants 1,2,4,8,16,....  
  • if so, the bit sequence actually is a smaller bit container within a bigger container
  • then the bit sequence actually is a group of flags or a combination of flags
  • the group of flags can be called a flag itself if the bit flags in the group are mutually exclusive,
  • i. e. one and only one of the bit flags in the group is set and all other are zero.
  • we can call the whole group a flag because we can test the whole group to match to any of the group values.
  • so we can say " the write-only flag of the access-mode flags is set" if the bitwise AND of flags and O_ACCMODE results in O_WRONLY.
  • another sample is a colour flag with (binary) values red = 001, yellow= 010, green = 100 and a colour mask constant coloured = 111.
  • because it cannot be both red and green, we can say that the red flag is set if the bit 0 of the extracted bit sequence of length 3 is set.
  • differently traffic lights may have both red and yellow lights on.
  • a bit group representing traffic lights  therefore is not a flag but a status
  • the value 0 would/should not be any of the colours but in case of traffic lights mean that all lights are off
  • the value 0 for a bit group should not be a valid flag value but should mean 'undefined' or 'not set'
  • same for a bit combination where more than one bit flag might be set.
  • a value of 0 for the combination means none of the bits is set.

note, if you have a bit group within a bit container, you can it extract by bitwise AND same as a single bit flag:

// these constants define a bit group for bit 1, bit 2, and bit 3 of a bit container
#define O_RDONLY     0x2 
#define O_WRONLY    0x4
#define O_RDWR         0x8
#define O_ACCMODE   O_RDONLY | O_WRONLY | O_RDWR  // == decimal 14 or hex 0xe

// define a variable flags which is a  bit container with 8 bits
byte flags = 0;

// test if any of the access modes is set 

if ((flags & O_ACCMODE) != 0)    // note flags = 00000000 and O_ACCMODE = 00001110
{
        // yes, at least one of the bit flags was 1
}
else
{
        // no,  none of the bit flags was 1
}

Open in new window


of course if flags = 0 all bits are 0 and the bit flag for each position is false.

// set any of O_RDONLY, O_WRONLY, O_RDWR
byte flags = O_RDONLY;  // flags = 00000010

// test if any of the access modes is set 

if ((flags & O_ACCMODE) != 0)    // note flags = 00000010 and O_ACCMODE = 00001110
{
        // yes, at least one of the bit flags was 1
}
else
{
        // no,  none of the bit flags was 1
}

Open in new window



here the result of bitwise AND is 00000010 because the 2nd bit is set both in flags and in the constant O_RDONLY.

do you see the difference if we would have defined O_RDONLY = 0.  the assignment had made no difference to the first sample code. flags would have been 0 and the bitwise AND has a zero result as well.

note, as told before O_RDONLY is not a flag but a constant which can used to test the 2nd bit of a bit container whether it is set or unset.

so, the flag is the 2nd bit of the bit container and the constant O_ACCMODE is called a mask which allows to check with an bitwise AND whether group of bit flags from position 1, 2, or 3 has at least one non-zero flag. the single constant O_RDONLY (if not 0) can be used to check a single bit flag of the container whether it is set or not set.

Sara
Also thanks a lot Sara! I noticed that you have a different point of view than some other people here, but I want to understand all the different point of views, so it's good that you're not thinking the same.

I'm pretty busy this week, so I still need to read your post more precisely, but I already have a question. In one way you're saying:

so the flag is the 3rd bit of a bit container (or bit set) with a size of at least 3 bits.

So you're saying:

first bit: 0
second bit: 0
third: 1 -> the 0 or 1 in this bit is called the flag

Then later on you're saying:

the group of flags can be called a flag itself if the bit flags in the group are mutually exclusive,
i. e. one and only one of the bit flags in the group is set and all other are zero.

So let's go back to our bit container of 3 bits (001). Here, only one of the three bits is set and all the others are zero. But now you call "001" as a whole a flag, while first you were saying:

the flag is the 3rd bit of a bit container

So for me this seems to contradict itself. First only the third bit is called a flag and now suddenly the three bits as a whole are called a flag. Or do we have to distinguish two different types of bit containers/bitsets according to you? A bitset with one bitflag ... or a bitset with multiple bit flags? Because it looks like that you're using different definitions of a flag for these two "types"?

001 can also be seen as a container for 3 bit flags (two bit flags not set, and one bit flag set). What is the difference between such a "001" and the first "001" what you were talking about (O_CREAT). Because from your point of view, both seems to have a different definition of "flag" (001 as a whole, or the third bit only).


And I also have problems with the term:

and we can use one-bit constants 2^0, 2^1, 2^2

Why you call this a "one-bit" constant? Because to make 2^2 (4) you need minimum 2 bits. You could say "one-bit-set constant". Is this your own term or is this a common used term? I think the term is a bit misleading. Or is there some other reason behind it why it's called like that? (except it's just shorter, but by leaving the word "set" behind actually the term becomes incorrect in my opinion so personally I would not use a term like that).
third: 1 -> the 0 or 1 in this bit is called the flag

no, the bit itself is the flag. in c you can define member variables of type char, short, int with a size in bits (it is best to use unsigned integers to not get confused with negative numbers).

struct Bit
{
      unsigned int onebit  : 1;
}; 

Open in new window



this onebit member variable is a equivalent to bool type but while the bool type (normally) has 8 bits (where only one is used), the onebit exactly has only 1 bit. that means if you assign 2 to the onebit it will have an overflow and the result is 0 cause the onebit only can use 1 bit and values 0 and 1.

struct Bits
{
      unsigned char bit0  : 1;
      unsigned char bit1  : 1;
      unsigned char bit2  : 1;
      unsigned char free : 5:
} ;    
; 

Open in new window


this sample shows how to define 3 bit flags in c (or c++) and a bit sequence of 5 bits. the whole size of the structure is 1 byte what is the minimum allocation size for a structure. the structure Bits therefore uses the space allocated anyhow by the compiler. the 'free' bits can be used for further flags and has the advantage that the size of the structure would not change as long as there are free bits.

the three bits as a whole are called a flag.

a 1-bit flag only is false or true. a 3 bit-flag has up to 7 values. if you say only one of the 3 bits is 1 we have only 4 states: no flag is set, the 1st flag is set, the 2nd flag is set or the 3rd flag is set. therefore the statement the 3 bit-flag is set valid if any of the three bit-flags is set. in real life we may have a beach which can be flagged with a green flag if the sea is calm, if it is windy they would use a yellow flag and if stormy the flag is red. in winter times the flagstick is empty what means the beach is not flagged at all.

so for a bit group we may have a more than one manifestations of the 'true' status and as long if the 0 state is well-defined i personally can't see a reason why the variable for the bit group cannot be named a flag. also in the structure Bits we could say free is a flag and it actually has no 'true' status at all cause it is always 0.

both seems to have a different definition of "flag" (001 as a whole, or the third bit only).
that was a bad wording from my side. if you have a bit group with in a bigger bit sequence, you may see the first bit of the bit group as 0-bit of the group or as the n-th bit of the bigger bit sequence where n includes the offset of the bit group related to the bit sequence. in the structure sample the 'free' group has offset 3 within the 8-bit structure.

Why you call this a "one-bit" constant?

as you assumed, the "one bit" constant means actully "one-bit-set" constant and is a term used by me only. i needed it  when both single bit flags and multiple bit flags were discussed to make clear that one-bit-constants are needed for to test a single bit-flag and that bit groups can be tested by constants where all bits of the group were set to 1.

not, an integer x which is a power of 2  (2^n) has only bit n set (n is 0-based) and all other bits are 0.
conversely, a constant which has only 1 bit set, say at position n, equals to 2^n. if you  build a new number y out of x which has all bits from 0 to n-1 be set to 1 and all higher bits are 0, you get y = x-1.

int n = 4;
int x = 2 * 2 * 2 * 2;  // = 2^4 = 0x10 hex = 16 decimal = 00010000 binary

// now set bit 0, bit 1, bit 2, bit 3 to 1
int y = 1 + 2 + 4 + 8;  // or y = 2^0 + 2^1 + 2^2 + 2^3

if (x == y + 1)
{
       // yes, if we have the (n-1) low bits set to 1 and increment by 1 we get 2^n, the next power of 2, 
       // where only bit n is set to 1 and all others are 0
}

Open in new window


"one-bit" constants can be used to test a bit flag at bit position n whether it is set or unset.

"multiple-bit" constants where a sequence of consecutive bits are 1 can be used to test a group of bits whether the bit-group is all 0 or not.

Sara
Okay I think I understand it. Actually in the end I noticed that @sara is the only one here who really understands flags. However, some things I see differently, but this has more to do with the correctness of some terms (not that she doesn't understand it, because she does). I'll try to explain what a flag is, just correct me if you think I'm wrong. It's a long post but this time it's worth reading it (if you want to understand flags the right way).

Step 1: Actually a flag is something that can be set or can not be set. In other words, it's something that has a value at one moment and it's something without a value at another moment. So e.g. a bit can be seen as a flag. When it's 1, it's set. When it's 0, it's not set. You have to compare the flag against something to notice whether or not the flag is set.

Step 2: The next step to realize is that the smallest unit to store things is not a bit, but a byte (8 bits). If we could store a single bit only (unit = bit), then we could see a flag as (I don't write it in c++, because I'm not used to it):

$flag_shoes = 1; (flag set, I'm wearing shoes)
or
$flag_shoes = 0; (flag not set, I'm not wearing shoes)

Now we could check:

if ( $flag_shoes == 1 ) {
	// Now we know that I'm wearing shoes
}

Open in new window


This is how flags would work if the smallest unit to store something is a bit. However, this is not the case.

Step 3: The smallest unit is 1 byte (8 bits), so in reality we have to see it as:

$flag_shoes = 00000001; (flag set, I'm wearing shoes)
or
$flag_shoes = 00000000; (flag not set, I'm not wearing shoes)

Now we could check:

if ( $flag_shoes == 00000001 ) {
	// Now we know that I'm wearing shoes
}

Open in new window


Now the flag is defined as 8 bits, with one bit being set (1) and the others being 0. We only need one bit to check whether or not I'm wearing shoes.

Step 4: In c++ you can not do something like:

if ( $flag_shoes == 00000001 ) {
	// Now we know that I'm wearing shoes
}

Open in new window


We need to compare $flag_shoes against something. Let's call this the compare-constant. So:

$compare_constant = 00000001;

if ( $flag_shoes == $compare_constant ) {
	// Now we know that I'm wearing shoes
}

Open in new window


However, this is still not possible in c++. Now we have to see it like something like this (bitwise and-operator):

$compare_constant = 00000001;

if ( $flag_shoes & $compare_constant == $flag_shoes ) {
	// Now we know that I'm wearing shoes
}

Open in new window


In other words, you can see it like this:

Case: $flag_shoes = 00000001

$flag_shoes       00000001
$compare_constant 00000001
-------------------------- &
                  00000001 => $flag_shoes is set

Case: $flag_shoes = 00000000

$flag_shoes       00000000
$compare_constant 00000001
-------------------------- &
                  00000000 => $flag_shoes is not set

Open in new window

     
So actually we're just using the compare-constant to check whether or not the flag is set. So whether the flag is 00000001 (set) or 00000000 (not set). So in this case, we can see the flag as: 00000000/00000001 (being 00000000 or being 00000001).

Step 5: Now we must realize that the previous step is a waste of bits. Seven bits are doing nothing, because we we only need one bit to determine whether something is true/false or 1/0. Now "bit flags" are coming in. The purpose of a "bit flag" is that less bits are wasted. We don't want 7 of the 8 bits being useless. In the next step I'll explain this further.

Step 6: Let's say we want to check 8 different things. Whether or not I'm wearing:

pants
shirt
shoes
socks
sweater
watch
bracelet
underpants

So we have 8 flags.

$flag_pants      = 00000000 or 00000001;
$flag_shirt      = 00000000 or 00000001;
$flag_shoes      = 00000000 or 00000001;
$flag_socks      = 00000000 or 00000001;
$flag_sweater    = 00000000 or 00000001;
$flag_watch      = 00000000 or 00000001;
$flag_bracelet   = 00000000 or 00000001;
$flag_underpants = 00000000 or 00000001;

Open in new window


Now we have 8 * (7 useless bits) = 56 bits wasted of the 64. Is there an alternative that will use/waste less bits? Maybe we could put all these flags in one byte:

flags_pants_shirt_shoes_socks_sweater_watch_bracelet_underpants = 0/1 0/1 0/1 0/1 0/1 0/1 0/1;

P.S. See 0/1 as a bit being 0 or 1.

Two examples:
11000000 refers to wearing a pants and waering a shirt.
00000011 refers to wearing a bracelet and an underpants.

But now we need 8 constants to compare it against. Each constant checks whether or not one specific bit of these 8 bits in "flags_pants_shirt_shoes_socks_sweater_watch_bracelet_underpants" is set. So now we have:

- flags_pants_shirt_shoes_socks_sweater_watch_bracelet_underpants = ???????? (8 bits)
- compare_constant_1 = 00000001; (8 bits)
- compare_constant_2 = 00000010; (8 bits)
- compare_constant_3 = 00000100; (8 bits)
- compare_constant_4 = 00001000; (8 bits)
- compare_constant_5 = 00010000; (8 bits)
- compare_constant_6 = 00100000; (8 bits)
- compare_constant_7 = 01000000; (8 bits)
- compare_constant_8 = 10000000; (8 bits)

So our purpose was to have less useless bits. Do we have less used bits now? First we used 64 bits. Now to accomplish the same, we have used 9*8=72 bits. So now we've used 8 (72-64) extra bits! This is not what we wanted, because we wanted to do the same thing in less bits.

Step 7: So far, we were talking about 8 flags that we wanted to use. But let's say we want to use 16 flags. We can do it like this:

$flag_1 		= 00000000 or 00000001;
$flag_2 		= 00000000 or 00000001;
$flag_3 		= 00000000 or 00000001;
$flag_4 		= 00000000 or 00000001;
$flag_5 		= 00000000 or 00000001;
$flag_6 		= 00000000 or 00000001;
$flag_7 		= 00000000 or 00000001;
$flag_8 		= 00000000 or 00000001;
$flag_9 		= 00000000 or 00000001;
$flag_10 		= 00000000 or 00000001;
$flag_11		= 00000000 or 00000001;
$flag_12		= 00000000 or 00000001;
$flag_13		= 00000000 or 00000001;
$flag_14		= 00000000 or 00000001;
$flag_15		= 00000000 or 00000001;
$flag_16		= 00000000 or 00000001;

Open in new window


And each of them we can compare against:

compare_constant = 00000001;

Total bits:

16*8 bits (16 flags)         = 128 bits
1*8 bits (compare-constant)  =   8 bits
                               --------  +
                               136 bits

Open in new window


But what if we would try to combine the flags. For 16 flags, we need 16 bits, so that are two constants of 8 bits. Now 8 compare-constants are enough, because the same compare-constants can be used for both flag-constants. So let's calculate how many bits we will use.

Two flag-constants (2*8 bits)    = 16 bits
Eight compare-constant (8*8bits) = 64 bits
                                   ------- +
                                   80 bits

Open in new window



So with the first method we're using 136 bits, but with the second method we're using 80 bits. So we've used 56 (136-80) bits less. This is what we wanted. We wanted to accomplish the same thing with less bits. This is actually the most important thing to understand. If you understand this, then the rest becomes logical. Without this, you will never understand "flags" for 100%.

Step 8: So what exactly is called a "bitset"? What is called a "bit field"? What exactly is called a "flag"? What exactly is called a "bit flag"? What is a "bitmask"?

FLAG: 000000001/00000000, 000000010/00000000 et cetera (just only one bit set)

BITSET / BIT FIELD: flags_pants_shirt_shoes_socks_sweater_watch_bracelet_underpants = 0/1 0/1 0/1 0/1 0/1 0/1 0/1; (there is a difference between bitset and bit field but that has more to do with their behavior)

BIT FLAG: Each "0/1" in flags_pants_shirt_shoes_socks_sweater_watch_bracelet_underpants

So if there are "bit flags" involved, then there are no "flags" involved. You just have to see both ("flags" and "bit flags") as two different methods of accomplishing the same thing.

Can we call a flag a value? No, we can not, because a flag refers to something like this 000000001/00000000. A value is just one thing, a value is X, or a value is Y, but a value can not be seen as X or Y. A variable can be seen as X or Y. The name "variable" already says that, the value can vary. However, the value of a value is just one thing.

@Sara: You said this:

the binary value (which has only 1 bit set and all others are zero)

I think it's better not to use the term "binary value" in this context. A "binary value" seeing like that is a contradictio in terminis in my opinion. You can say a "binary variable", because then "something" is variable and BI-nary refers to: variable in two ways (0 or 1, true or false). And this is exactly why a flag can not be seen as a "predefined value". A value is not VARIABLE because it doesn't vary (it's only about ONE value). However, a flag is something that varies (that is variable) in two ways (0 or 1). If a flag wouldn't be variable, then it would NOT be possible to unset the flag, because then a flag wouldn't be a flag anymore. You can compare this with:

$variable = value;
unset( $variable );

// Now $variable still exists, but it has no value (0). So $variable is something that is "something" or that is "not something".
// A variable is not a value, but a variable can hold a value. This is a important difference.

Open in new window


So in the end, we can not say that a flag is a value, but we can say that a flag is a "binary VARIABLE", so it's variable in two ways.

What is a bitmask? It's not that important in this story, but let's take a look again at:

flags_pants_shirt_shoes_socks_sweater_watch_bracelet_underpants = 0/1 0/1 0/1 0/1 0/1 0/1 0/1;

Usually one bit will be changed (0/1). A bitmask can change multiple bits at once. So let's say we have: 00000000. A bitmask can make 11000000 of it at once, while otherwise you had to do:
step 1: 00000000 -> 10000000
step 2: 10000000 -> 11000000
So this in not really important for the question about flags.

By the way @sara:

third: 1 -> the 0 or 1 in this bit is called the flag

no, the bit itself is the flag.

I think you're saying exactly the same as I'm saying, because 0/1 (0 or 1) is the bit.

So now to end with, we have to go back to O_CREAT, O_RDONLY et cetera.

Firstable, the question we have to ask ourselves is: is it about "flags" or is is about "flag bits"?  Actually it's not about flags at all, because in this case it's about "bit flags" (not flags). The bit-flags-method is used to waste less bits. Now let's take a look at:

#define O_CREAT            00000100      /* not fcntl */

Open in new window


This is not a "flag" or "bit flag". A flag is something that is either A or either B (0/1, something or not something). So O_CREAT can never be a flag or bit flag. You must see O_CREAT as the "compare-constant" (discussed earlier in this post). So it's the value that is used to compare the flag or bit flag against. Now let's take a look at: http://man7.org/linux/man-pages/man2/open.2.html

int open(const char *pathname, [b]int flags[/b]);

Open in new window


"int flags" is actually a bit misleading here, because actually it's about bit flags here. It's about which bit flag you will set and which one unset (default is unset). If it would be about flags, then it would NOT be necessary to use (as comparison-constants):

00000001
00000010
00000100
00001000
et cetera

Then we could just use one compare-constant (00000001 from earlier in this post). But as we see ... with all the different "define O_", we see that the compare-constants do not all hold the same value. That has an important reason, because that's the method discussed above to waste less bits.

So how we have to see "int flags" in the open() system call? "int flags" is actually not about flags, it's about bit flags, so it's about setting one specific bit in a sequence of bits (eight in our example). So compare it with:

flags_pants_shirt_shoes_socks_sweater_watch_bracelet_underpants = 0/1 0/1 0/1 0/1 0/1 0/1 0/1;

With "int flags", it's about one specific 0/1 in this row/sequence of bits. You will change 0 in 1 in one specific bit. You're setting the bit. Or in other words, you're setting the bit flag. So it's not about flags, but it's about bit flags.

So if we're talking about for example O_CREAT, we have actually two different O_CREAT's.

1. O_CREAT used in "int flags". (let's call it O_CREAT-int-flags)
2. O_CREAT used in "define O_CREAT".  (let's call it O_CREAT-define)

The first one is about the "bit flag". The second one is about the "compare-constant".

Now let's take a look at:

#define O_ACCMODE     00000003
#define O_RDONLY      00000000
#define O_WRONLY      00000001
#define O_RDWR        00000002

Open in new window


To keep it simple, imagine that the computer could store units of two bits (instead of eight bits / one byte). Then you can see this in bits as:

#define O_ACCMODE     11 (00000003)
#define O_RDONLY      00 (00000000)
#define O_WRONLY      01 (00000001)
#define O_RDWR        10 (00000002)

Open in new window


Again the question: are these constants flags or bit flags? No they are not, because it's not something that varies between two values (0/1, false/true, not something or something). These constants will be compared against "something". Can we see that "something" as "flags" or "bit flags? That's actually what the question is about. In other words:

flag/bit-flags & O_ACCMODE == flag/bit-flags

Would it make any sense to check this?

O_WRONLY & O_ACCMODE == O_WRONLY (01 & 11 = 01, so TRUE)
O_RDWR & O_ACCMODE == O_RDWR (10 & 11 = 10, so TRUE)

Actually it's pretty useless, because:
something & O_ACCMODE (11) IS ALWAYS equal to the same something

So we can not see it like that. But we can see it like this:

if ( something & O_ACCMODE == 01 (O_WRONLY) ) {
	// write only
} elseif ( something & O_ACCMODE == 10 (O_RDWR) ) {
	// read and write
} else {
	// read only
}

something = O_RDONLY-int-flags or O_WRONLY-int-flags or O_RDWR-int-flags;

Open in new window


Now let's go back to 8 bits sequences instead of 2 bits sequences:

?????? = 0/1 0/1 0/1 0/1 0/1 0/1

if ( ??????something & 00000011 (O_ACCMODE) == 00000001 (O_WRONLY) ) {
	// write only
} elseif ( ??????something & 00000011 (O_ACCMODE) == 00000010 (O_RDWR) ) {
	// read and write
} else {
	// read only
}

something = O_RDONLY (00) or O_WRONLY (01) or O_RDWR (10);

Open in new window


So using O_RDONLY in the open() call is the same as not using O_RDONLY in the open() call. That's why "00" can be used as value for O_RDONLY. So O_RDONLY can not be seen as a "flag" or "bit flag" for sure. It's not something that is 0/1 (bit set, or bit not set). It's just always 00.

Now let's say we're putting O_WRONLY in the open() call. If it would be a "bit flag", then a bit must be set as a result of putting O_WRONLY in open(). Actually we can see it like that because O_WRONLY in the open() call (let's call it O_WRONLY-int-flags), can be seen as:

set: ??????01
unset: ??????00
So O_WRONLY-bit-flag: ??????00/??????01

P.S. With each "?" being 0/1.

So in some way we can see O_WRONLY and O_RDWR as a "bit flag". Again, anyway they can not be called "flags", because both are part of the same bit sequence. So again the bit-flag-method is used to waste less bits. The different "flags" (O_WRONLY-int-flags and O_RDWR-int-flags) are part of the same byte (same bit sequence). This means it can not be called a flag anymore, but we have to call it a "bit flag". However, there is a difference with for example O_CREAT and that's exactly the reaon why in some way you can also see them (O_WRONLY-int-flags and O_RDWR-int-flags) as NOT being bit flags. The difference is the way of comparing. When it's about "real" bit flags, the comparison is as follows:

When it's about things like O_RDONLY:
bit flag & compare-value == bit flag

When it's about things like O_WRONLY/O_RDWR:
?????? = 0/1 0/1 0/1 0/1 0/1 0/1

if ( ??????something & 00000011 (O_ACCMODE) == 00000001 (O_WRONLY) ) {
	// write only
} elseif ( ??????something & 00000011 (O_ACCMODE) == 00000010 (O_RDWR) ) {
	// read and write
} else {
	// read only
}

something = O_RDONLY (10) or O_WRONLY (01) or O_RDWR;

Open in new window


So in some way we can see it as:

O_RDONLY 10/00
O_WRONLY 01/00
O_RDWR   00/00

P.S. When it's about O_RDWR ... because of the 00/00 (not set/not set), O_RDWR can not be called a "bit flag" or "flag" for sure.

Personlly I would not call O_RDONLY and O_WRONLY "bit flags", because when you have a "bit flag" in a sequence of bits, the "bit flag" is independent of all other bits in the sequence. However, with for example O_RDONLY and O_WRONLY, this is not the case. If we see it as two bits (to make it easier to follow):

bit 1 (O_RDONLY): 0/1
bit 2 (O_WRONLY): 0/1

If bit 1 (O_RDONLY) is 1, then bit 2 (O_WRONLY) must be 0. So they are dependent of each other and a bit that acts as "bit flag" is not dependent of other bits. So in the end, I would say: O_RDONLY, O_WRONLY, O_RDWR and O_ACCMODE are not flags or bit flags.

O_ACCMODE acts as mask. A mask is something that hides some parts of your face while showing the other parts. So let's tke a look at:

#define O_ACCMODE   00000011 (8 bits, byte)
#define O_RDONLY    00000000 (8 bits, byte)
#define O_WRONLY    00000001 (8 bits, byte)
#define O_RDWR      00000010 (8 bits, byte)

Open in new window


Now we can see "int flags" from the open() as:

?????? 0/1 0/1

P.S. ? can be seen as 0/1

So we have eight different bits, the state/value of six bits are unknow the other two can be: 00, 01 or 10. The mask O_ACCMODE hides 6 bits and shows 2 bits (that's why it's called a mask). So you will end up with:

00, or
01, or
10

Open in new window


The result (01, 10 or 00) will be checked against something (O_RDONLY-define, O_WRONLY-define, O_RDWR-define) to check which one of these three is the result. So now we're pretty much there. We've explained everything.

Now let's go back to this definition:

In computer science, a flag is a value that acts as a signal for a function or process. The value of the flag is used to determine the next step of a program. Flags are often binary flags, which contain a boolean value (true or false). However, not all flags are binary, meaning they can store a range of values.

As I explained before, a flag is not a value. This definition is incorrect anyway. @Mihai:

So, basically, a flag is a value we can read and / or set, that indicates that a condition is met (or not).

Again, flag != value. A value can not be set, a variable can be set. These are important differences if you want to understand it 100%. @Fabrice:

First, a flag is a value

Same mistake.

And about this part:

However, not all flags are binary, meaning they can store a range of values.

This is not correct in my opinion (but it's a difficult one). Officially a flag is just something like 00000000/00000001. You can also see it as for example 00000000/some-word, 0/1, false/true et cetera bit it's always about something/not-something (BI-nary). You can combine different flags in one bit sequence, but then it's not called a flag anymore (then it's a bit flag). That's exactly the reason why a flag can not be seen as storing "a range of values". You need more than one bit to store more than two "values" (0/1).

Now let's go back to the other definition:

In programming, a flag is a predefined bit or bit sequence that holds a binary value. Typically, a program uses a flag to remember something or to leave a sign for another program. For example,  in a message being exchanged by two programs, a three-bit flag's field or data area might be set to one of three configurations:

A "predifined bit"?? A bit is 0/1. Let's say a bit is pre-defined and it's just 1 or just 0. Then it's not a bit anymore. So how I have to see a "predefined bit"? It looks like this term shouldn't have been used.

@Mihai:

If you fill a bit field with flags

This is incorrect. A bit field is filled with "bit flags", not with flags! When they are part of a field that contains other "flags", then a "flag" is not called a "flag" anymore, but a "bit flag".

@Mihai:

O_CREAT is a 1 bit flag

You can not say it like that. First you have to distinguish (as explained before in this post):

1. O_CREAT-define
2. O_CREAT-int-flags

Now you can say that O_CREAT-int-flags can be seen as a bit flag. However, O_CREAT-define is about the compare-constant. So in general, you can not say that O_CREAT is 1 bit flag.

In particular, I want to thank @sara for her second last post, because that actually opened my eyes and I started thinking in a certain direction to come to the conclusion discussed in this post. Anyway, also thanks to all the other "posters". Maybe I'm still wrong about some things, but then just correct me. My knowledge is not fixed, I'm always open to better arguments than I've collected so far.
Note:
Since C++11, the container std::bitset is available, wich represent any amount of bits:
https://en.cppreference.com/w/cpp/utility/bitset
It looks like this website has some problems with my previous post. At least I see a part of it at the bottom of this page. It ends with "arguments than I've collected so far." so then you know if you saw the whole post.

And @Fabrice: thanks for the note. See this quote of me:

BITSET / BIT FIELD: flags_pants_shirt_shoes_socks_sweater_watch_bracelet_underpants = 0/1 0/1 0/1 0/1 0/1 0/1 0/1; (there is a difference between bitset and bit field but that has more to do with their behavior)

Is there some reason why you're specifically noticing that about the bitset? Maybe I'm not aware of something or I see something te wrong way? I thought that it's not that important when it's about flags, because the "bit sequence" is important. If it's in the end a "bit field" or a "bitset", that doesn't really change the principles behind it (only some operations on it are easier to accomplish). But just correct me if I'm wrong about it.

So it's just about a row/sequence of bits and that's already enough to know.
Is there some reason why you're specifically noticing that about the bitset?
The reason is that std::bitset is a strongly typed class specifically made to handle bits.
While native variable types (char, int, long ect ....) can be used for other purpose.
Ah okay thank! That's also what I meant with:

there is a difference between bitset and bit field but that has more to do with their behavior

If it's in the end a "bit field" or a "bitset", that doesn't really change the principles behind it (only some operations on it are easier to accomplish).

So because it's specially made for it, some things are easier to accomplish.
yes, i agree with all regarding bit flag and "compare" constants.

the only addition i would like to make is that a sequence of bit flags in my opinion still can be called "a flag". for example if 01 is red and 10 is green and 11 is yellow, we can say that the 2-bit sequence is a flag which is unset when the two bits are 0, it is flagged red when the two bits are 01, it is flagged green, when the two bits are 10 and it is flagged yellow, when both the bits are set.

you may see it as a flag where the 'true' part has different flavours. in real life you could imagine a flagstick which can be empty or was flagged either with a red, green, or yellow flag.


note, if there is a group of bit flags where one or more can be true or false, the group itself is definitively not a flag.


Sara
the std::bitset class is a helper template class. template means that it is parameterized with the number of bits you can manage with this class. by using bitset you are Independent of 8-bit container 'byte', 16-bit container 'unsigned short', 32-bit container 'unsigned int' or 64-bit container 'unsigned long long'.  you simply could use std::bitset<48> bits48.


unfortunately this class has some pitfalls because for example std::bitset<48> and std::bitset<24> are different types which can't be transformed into another without problems. so actually std::bitset is not very handy and doesn't give an input for the flag discussion.


Sara
Thanks a lot again Sara!

the only addition i would like to make is that a sequence of bit flags in my opinion still can be called "a flag". for example if 01 is red and 10 is green and 11 is yellow, we can say that the 2-bit sequence is a flag which is unset when the two bits are 0, it is flagged red when the two bits are 01, it is flagged green, when the two bits are 10 and it is flagged yellow, when both the bits are set.

I agree, but usually the mimimum is 8 bits (8-bit sequence) so then I think we have to call the 2-bit sequence as a whole a "bit flag" (instead of just a "flag"), because the 2-bit sequence is part of a bigger sequence and those bits are usually/probably used for other bit flags. Usually then it's called a "bit flag" and not a "flag", so it would be logical to use the same terms when it's about multiple bits. But in theory it's also possible that the other bits (8-2=6) are just: 0 instead of: 0 or 1, so then it can be called a "flag", but then the the 8-bit sequence must be called a flag (not the 2-bit sequence that is part of the 8-bit sequence).

P.S. I'm pretty busy coming weeks, but when I have a bit more time I'll mark (answer et cetera) all the posts in this question.
This question needs an answer!
Become an EE member today
7 DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform.
View membership options
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.