I'm learning about Pawn language . I'm having trouble with parameters in the enum function
enum E_MY_TAG (<<= 1)
{
E_MY_TAG_NONE,
E_MY_TAG_VAL_1 = 1,
E_MY_TAG_VAL_2,
E_MY_TAG_VAL_3,
E_MY_TAG_VAL_4
}
new
E_MY_TAG:gMyTagVar = E_MY_TAG_VAL_2 | E_MY_TAG_VAL_3;
I learned that the values in the enum will increment by default by +=1
And my lesson says the code :
new E_MY_TAG:gMyTagVar = E_MY_TAG_VAL_2 | E_MY_TAG_VAL_3;
That will create a new variable and assign it the value 6 (4 | 2)
I don't understand it , why the value of E_MY_TAG_VAL_2 is 4 and E_MY_TAG_VAL_3 is 2 and the parameter in the enum function why it is <<=1 , i remember there is no such operator
This enumerator contains bit flag values. First enum value is implicitly initialized with 0, second is explicitly initialized with 1, and the rest are initialized by applying <<=1 (left bit shift operator that is essentially equivalent to multiplying by 2) to the previous value and will be 2, 4, 8. gMyTagVar is composed using bitwise OR operator. You may want to get familiar with bitwise operations.
Related
i need to work with "indicator" variables I that may take on one of 3 integer values {-1, 0, 1}.
so i would rather not declare
int I;
but rather
indicator_t I;
where the type indicator_t ~ {-1, 0, 1}
if furthermore i can later use I in numerical expressions, as an integer (without casting?), that would be excellent.
question:
how should i define the type indicator_t?
The simplest approach would be to convert the tri-state input into an enum class with 3 fixed discriminators:
enum class indicator_t {
negative = -1,
zero = 0,
positive = 1,
};
There are several nice things with this approach:
It's simple, which makes it easy to understand and maintain
enum class makes it a unique type from ints, which allow both the enum and an integer to appear as part of an overload set, if needed
The enum logically has a cardinality of 3 (the type can accept 3 logical inputs). 1
This cardinality prevents code that would otherwise be like a != 22 even though 2 is never a possible input
When inputs are passed to a function accepting indicator_t, it's clear from the call-site the intention. Consider the difference between the following two code snippets:
accept(1); // is this an indicator?
accept(indicator_t::positive); // ah, it's an indicator
If you need to convert to / from numeric values, you can create simple wrappers for this as well:
auto to_int(indicator_t indicator) -> int
{
return static_cast<int>(indicator);
}
auto to_indicator(int indicator) -> indicator_t
{
if (indicator > 1 || indicator < -1) {
// handle error. Throw an exception?
}
return static_cast<indicator_t>(indicator);
}
1 Technically C++ enums can take on any integral value that fits in std::underlying_type_t<the_enum>, but this doesn't change that the logical valid set of inputs is fixed, which prevents developer bugs. Compilers will even try to warn on checks outside of the logical range.
2 Technically this could still be done, but you'd need to explicitly static_cast all the time -- so it would appear as a code smell rather than a silently missed logic bug.
i am trying to create an enum flag that would see if a certain thing was bold and italic, but i am getting compilation error:
error: cannot initialize a variable of type 'designFlags' with an rvalue of type 'int'
designFlags myDesign = BOLD | UNDERLINE;
#include <iostream>
using namespace std;
enum designFlags {
BOLD = 1,
ITALICS = 2,
UNDERLINE = 4
};
int main()
{
designFlags myDesign = BOLD | UNDERLINE;
// 00000001
// | 00000100
// ___________
// 00000101
cout << myDesign;
return 0;
}
The C++ standard prevents you from performing an implicit cast from int to enum (Note: implicit conversion from enum to int is allowed).
However, you can perform an static cast instead:
designFlags myDesign = static_cast<designFlags>(BOLD | UNDERLINE);
cout << myDesign; // prints 5
Have in mind that it is most like that the resulting value is not one of the values specifies in designFlags. This is usually a common practice, but you have to rely to bit-wise operations to perform comparisons:
For example:
// wrong
if (myDesign == BOLD)
// ok (most of the time)
if (myDesign & BOLD)
// always ok
if ((myDesign & BOLD) == BOLD)
Update: Why is myDesign & BOLD ok most of the time?
When you use flags, the values must be powers of two: 1, 2, 4, 8, etc. Therefore, every possible value has only one bit set, and this bit is different for each one.
Then, when you do myDesign & BOLD, you are testing for one specific bit, and just that. If the bit is set, the result will be non-zero (bitwise AND). If the bit it not set, the result will be zero.
When it can go wrong? Well, if you use flags that are not a power of two, each individual value will have more than one bit set, making it difficult to perform these checks.
For instance, suppose you have this definition:
enum designFlags {
BOLD = 2,
ITALICS = 4,
UNDERLINE = 6
};
And then you set your design to UNDERLINE:
myDesign = UNDERLINE
What is the result of the following tests?
myDesign & BOLD
myDesign & ITALICS
It will be non-zero for both of them, surely an undesired behavior.
Of course you can do the following:
if ((myDesign & BOLD) == BOLD) {
...
but i rather use flags with only one bit set.
I browsed through the internet and got to know that it is a compound assignment operator. But how does it work?
I used this link to get to know about the definition, but I couldn't find the exact implementation of this syntax.
In the link that you provided, there is a code snippet that uses a compound assignment operator:
a+=2; // equivalent to a=a+2
The >>= operator also works in a similar way:
a>>=2; // equivalent to a=a>>2
>> is called as the (Right) Shift operator, and shifts the source operand's binary representation to the right by a certain number of bits. For instance, let us have this code snippet:
int a=12;
cout<<a<<endl;
a>>=2;
cout<<a<<endl;
The output of the code segment, when executed with a C++ compiler will be:
12
3
What exactly happens is this: a has the value of 12, which is represented in binary as (only showing the last 6 bits) 001100. a>>=2; shifts the bits in a by 2 places to the right and assigns the new value to a, hence the new bit positions become 000011, which is 3 in decimal, and hence a gets the value of 3, and the resulting output.
Hope this clarifies the confusion.
>> is the right shift operator.
As you mentioned >>= is a compound assignment operator. A compound assignment modifies the variable with the operator and assigns the new value to itself.
a >>= b is equivalent to a = a >> b
i.e., a is right shifted b times and assigned back to a.
For example,
int a = 8, b = 2;
a >>= b; // right shift by 2 i.e. divide by 2 x b times.
cout << a; // prints value of 2
I'm trying to understand a C++ code given here. Apologies if the question is too basic, but I am not a regular C++ coder.
Here are two Enums defined in the code and a a few functions that operate on the Enums:
...
enum Value {
VALUE_ZERO = 0,
VALUE_DRAW = 0,
VALUE_KNOWN_WIN = 10000,
VALUE_MATE = 32000,
VALUE_INFINITE = 32001,
VALUE_NONE = 32002,
...
};
...
/// Score enum stores a middlegame and an endgame value in a single integer.
/// The least significant 16 bits are used to storethe endgame value and
/// the upper 16 bits are used to store the middlegame value. ...
enum Score {
SCORE_ZERO,
SCORE_ENSURE_INTEGER_SIZE_P = INT_MAX,
SCORE_ENSURE_INTEGER_SIZE_N = INT_MIN
};
inline Score make_score(int mg, int eg) {
return Score((mg << 16) + eg)
}
/// Extracting the signed lower and upper 16 bits is not so trivial ...
inline Value mg_value(Score s) {
union {uint16_t u; int16_t s;} mg = {uint16_t(unsigned(s + 0x8000) >> 16)};
return Value(mg.s);
}
inline Value eg_value(Score s) {
union {uint16_t u; int16_t s;} eg = {uint16_t(unsigned(s))};
return Value(eg.s);
}
Questions:
(a) From my basic understanding of Enum in C++, SCORE_ZERO in the enum Score gets a value of 0, and thus the set of values of enum Score is 0, MAX_INT, or MIN_INT. The function make_score seems to accepts any two int (mg, eg) and returns an instance of Score. How does it (or the compiler) decide whether to return Score with value assigned to one out of 0, MAX_INT, or MIN_INT?
(b) Similar, the Enum Value only has a fixed set of values. How does Value(mg.s) in the function mg_value, or Value(eg.s) in the functioneg_valuedecide which values fromValue` to pick?
(c) In general, if XYZ is an Enum and a function returns XYZ(n) where n is not a value already defined in Enum, how is the Enum initialized?
How does it (or the compiler) decide whether to return Score with value assigned to one out of 0, MAX_INT, or MIN_INT?
It doesn't. When you force a cast to Score using Score((mg << 16) + eg), you can use any value, not necessarily one of the above declared constants.
It is valid to use:
Score s1 = (Score)10;
Score s2 = Score(20);
How does Value(mg.s) in the function mg_value, or Value(eg.s) in the function eg_value decide which values from Value to pick?
It doesn't. The answer to the previous question regarding Score applies here as well.
In general, if XYZ is an enum and a function returns XYZ(n) where n is not a value already defined in the enum, how is the enum initialized?
The answer to the first question applies here as well. The compiler doesn't guarantee that the value of a variable of type XYZ will be one of the constants defined in the enum.
I am new to C++ and have programming knowledge only in Java. Can anyone please explain the meaning of the code below:
#define DEF 134 ;
int k;
char msk;
PMSK *pm; //At the begining of class some declaration
// i is some counter(int)
if ( (nVersion >= 2004) && (nVersion < 2008))
{
k = to_bits(DEF, &msk);
if ( pm->orbits[k] & msk ) // for version >= 2004
{
x = atoi( grprs[i] );
if ( !defpair( i, x ) )
pm->orbits[k] &= 0xFF ^ msk; // turn off bit
}
}
to_bits() is method which will return an integer value and a (char) msk value (example 1000). It has bit operations involved in it.
What is pm->orbits[k]? Can we replace it in Java like pm.orbits[k]?
Also, what exactly the last line of code doing?
What is pm->orbits[k]? can we replace it in java like pm.orbits[k]?
Basically, yes. The -> operator de-references and then access a field (also known as access the field/function of the object pointed to by the pointer). However, if you had a reference type to begin with, you get the de-referencing "for free".
PMSK *pm1; // assume this has been initialized to point to something valid
PMSK &pm2; // assume this is a valid reference
PMSK pm3; // assume this is a valid declaration
pm1->orbits[0]; // accesses field orbits[0] of object pointed to by pm1
(*pm1).orbits[0]; // equivalent to above statement
pm2.orbits[0]; // it's implicitly understood that de-referencing should take place
pm3.orbits[0]; // no need to dereference
Dissecting the last line of code:
pm->orbits[k] &= 0xFF ^ msk; // turn off bit
^ is the bitwise exclusive or operator (a.k.a. xor). Basically it returns a bit value of 1 if both bits are not equal and 0 otherwise.
&= is the bitwise-and assigment operator. Equivalent to the following:
pm->orbits[k] = pm->orbits[k] & (0xFF^msk);
The bitwise and operator matches up equivalent bits and determines if both are 1. If they are, the result is 1. Otherwise, it's 0. So 100001 & 100100 = 100000 (binary numbers).
So it takes whatever's in msk, toggles the lowest 8 bits (1 -> 0 and 0 -> 1), then bitwise-ands that with the current pm->orbits[k] field. Finally, it assigns the result back to pm->orbits[k]
In Java, it's required to have an explicit check to somehow convert the results from a number to a boolean. However, in C++ it's implicitly understood that anything which isn't 0 is true.
if(1) // same as if(1!=0)
if(2) // same as if(2!=0)
if(0) // same as if(0!=0)
if(-1) // same as if(-1!=0)
Yes you can replace the code you mention. The '->' operator dereferences a pointer to a PMSK object. Java doesn't have pointers, only references, but they are used in the same way.
The last line is clearing the bits set in msk, however it's normally done like this:
pm->orbits[k] &= ~msk;
If you want to set the bits in msk, you'd use:
pm->orbits[k] |= msk;
Also, the following line will need to evaluate to a boolean expression, where as in C++ it just needs to be non-zero:
if ((pm->orbits[k] & msk) != 0)
{
...
}
What is pm->orbits[k]? can we replace
it in java like pm.orbits[k]?
Yes, pm is a pointer, and the -> notation is how to access members on a pointer.
The last line is a bitwise operation, called an exclusive or, the ^ operator is the same and does the same thing in Java.
The -> operator dereferences a pointer to select a field.
The last line of code does a bitwise exclusive or (XOR) of the msk value with 0xFF. This value is then bitwise ANDed with the pm->orbits array value at index k.
A few subjects that are going to help as you learn C++ and work with this code
Pointers in general
http://www.cplusplus.com/doc/tutorial/pointers/
C++ for Java Programmers ht
Bitwise operations in general http://vipan.com/htdocs/bitwisehelp.html
Arrays in C++
Passing by reference and value
Just about any introductory C++ text will have this info.