I've been going through an old source project, trying to make it compile and run (it's an old game that's been uploaded to GitHub). I think a lot of the code was written with C-style/C-syntax in mind (a lot of typedef struct {...} and the likes) and I've been noticing that they define certain macros with the following style:
#define MyMacroOne (1<<0) //This equals 1
#define MyMacroTwo (1<<1) //This equals 2, etc.
So my question now is this - is there any reason why macros would be defined this way? Because, for example, 0x01 and 0x02 are the numerical result of the above. Or is it that the system will not read MyMacroOne = 0x01 but rather as a "shift object" with the value (1<<0)?
EDIT: Thanks for all of your inputs!
It makes it more intuitive and less error prone to define bit values, especially on multibit bitfields. For example, compare
#define POWER_ON (1u << 0)
#define LIGHT_ON (1u << 1)
#define MOTOR_ON (1u << 2)
#define SPEED_STOP (0u << 3)
#define SPEED_SLOW (1u << 3)
#define SPEED_FAST (2u << 3)
#define SPEED_FULL (3u << 3)
#define LOCK_ON (1u << 5)
and
#define POWER_ON 0x01
#define LIGHT_ON 0x02
#define MOTOR_ON 0x04
#define SPEED_STOP 0x00
#define SPEED_SLOW 0x08
#define SPEED_FAST 0x10
#define SPEED_FULL 0x18
#define LOCK_ON 0x20
It is convenient for the humans
for example
#define PIN0 (1u<<0)
#define PIN5 (1u<<5)
#define PIN0MASK (~(1u<<0))
#define PIN5MASK (~(1u<<5))
and it is easy too see if there is a correct bit position. it does not make the code slower as it is calculated at the compile time
You can always use constant integer expression shifts as a way to express (multiples of) powers of two, i.e. Multiple*(2 to the N-th power) = Mutliple << N (with some caveats related to when you hit the guaranteed size limits of the integer types and UB sets in*) and pretty much rely on the compiler folding them.
An integer expression made of integer constants is defined as an integer constant expression. These can be used to specify array sizes, case labels and stuff like that and so every compiler has to be able to fold them into a single intermediate and it'd be stupid not to utilize this ability even where it isn't strictly required.
*E.g.: you can do 1U<<15, but at 16 you should switch to at least 1L<<16 because ints/unsigneds are only required to have at least 16 bits and leftshifting an integer by its width or into the place where its sign bit is is undefined (6.5.7p4):
The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated
bits are filled with zeros. If E1 has an unsigned type, the value of
the result is E1 x 2E2 , reduced modulo one more than the maximum
value representable in the result type. If E1 has a signed type and
nonnegative value, and E1 x 2E2 is representable in the result type,
then that is the resulting value; otherwise, the behavior is
undefined.
Macro are just replacement text. Everywhere macro is replaced by replacement text!! This is convenient especially if you want to name something constant which otherwise is prone to mistakes.
To illustrate how this (1<<0) syntax is more practical, consider this example from the code-base of Git 2.25 (Q1 2020), which moves the definition of a set of bitmask constants from 0ctal literal to (1U<<count) notation.
See commit 8679577 (17 Oct 2019) by Hariom Verma (harry-hov).
(Merged by Junio C Hamano -- gitster -- in commit 8f40d89, 10 Nov 2019)
builtin/blame.c: constants into bit shift format
Signed-off-by: Hariom Verma
We are looking at bitfield constants, and elsewhere in the Git source code, such cases are handled via bit shift operators rather than octal numbers, which also makes it easier to spot holes in the range.
If, say, 1<<5 was missing:
it is easier to spot it between 1<<4 and 1<<6
than it is to spot a missing 040 between a 020 and a 0100.
So instead of:
#define OUTPUT_ANNOTATE_COMPAT 001
#define OUTPUT_LONG_OBJECT_NAME 002
#define OUTPUT_RAW_TIMESTAMP 004
#define OUTPUT_PORCELAIN 010
You get:
#define OUTPUT_ANNOTATE_COMPAT (1U<<0)
#define OUTPUT_LONG_OBJECT_NAME (1U<<1)
#define OUTPUT_RAW_TIMESTAMP (1U<<2)
#define OUTPUT_PORCELAIN (1U<<3)
Related
code as follows:
'''
int __stdcall xloper_type(const xloper *type){
if(type->xltype&~(xlbitXLFree|xlbitDLLFree)==xltypeRef)
return xltypeRef;
}
'''
why to use ~(xlbitXLFree|xlbitDLLFree) when testing pointer type's xltype?? thanks!
Below is the relevant section from xlcall.h which defines the XLOPER data type. I don't know how 'xloper' (lower case) is defined in the OP's code (whether XLOPER or XLOPER12), but for XLOPER the xltype member is an unsigned int (WORD). Each bit corresponds to a different flag, so you can use bit-wise operations.
The xlbitXLFree and xlbitDLLFree are bits that indicate who (Excel or you) is responsible for cleaning up any memory allocated to the OPER (eg if it contains a string, or array). So typically, if you allocate any memory for the OPER in your xll, the xlbitDLLFree bit will be set to 1, and Excel will expect you to tidy up afterwards (passing the OPER to the xlAutoFree() function that should be declared somewhere in your xll code).
So
type->xltype&~(xlbitXLFree|xlbitDLLFree)
zeroes out the memory allocation bits in a bit-wise AND NOT() operation, leaving you with just the basic type. Eg if you received a string from Excel into your code, it's xltype would likely be xltypeStr & xlbitXLFree (Excel will tidy up), so 0x1002, which would not be equal to xltypeStr (0x0002), hence the need the bit-wise operation before you check for the OPER underlying type.
A neater way to write this might be (depending on requirements)
if(type->xltype & xltypeRef) {}
as the result will be non-zero (true) if the bit matching xltypeRef (0x0008) is set in type->xltype.
/*
** XLOPER and XLOPER12 data types
**
** Used for xltype field of XLOPER and XLOPER12 structures
*/
#define xltypeNum 0x0001
#define xltypeStr 0x0002
#define xltypeBool 0x0004
#define xltypeRef 0x0008
#define xltypeErr 0x0010
#define xltypeFlow 0x0020
#define xltypeMulti 0x0040
#define xltypeMissing 0x0080
#define xltypeNil 0x0100
#define xltypeSRef 0x0400
#define xltypeInt 0x0800
#define xlbitXLFree 0x1000
#define xlbitDLLFree 0x4000
I am reading The C++ Answer Book by Tony L Hansen. It says somewhere that the value of SHRT_MAX (the largest value of a short) can be derived as follows:
const CHAR_BIT= 8;
#define BITS(type) (CHAR_BIT*(int)sizeof(type))
#define HIBIT(type) ((type)(1<< (BITS(type)-1)))
#define TYPE_MAX(type) ((type)~HIBIT(type));
const SHRT_MAX= TYPE_MAX(short);
Could someone explain in simple words what is happening in the above 5 lines?
const CHAR_BIT= 8;
Assuming int is added here (and below): CHAR_BIT is the number of bits in a char. Its value is assumed here without checking.
#define BITS(type) (CHAR_BIT*(int)sizeof(type))
BITS(type) is the number of bits in type. If sizeof(short) == 2, then BITS(short) is 8*2.
Note that C++ does not guarantee that all bits in integer types other than char contribute to the value, but the below will assume that nonetheless.
#define HIBIT(type) ((type)(1<< (BITS(type)-1)))
If BITS(short) == 16, then HIBIT(short) is ((short)(1<<15)). This is implementation-dependent, but assumed to have the sign bit set, and all value bits zero.
#define TYPE_MAX(type) ((type)~HIBIT(type));
If HIBIT(short) is (short)32768, then TYPE_MAX(short) is (short)~(short)32768. This is assumed to have the sign bit cleared, and all value bits set.
const SHRT_MAX= TYPE_MAX(short);
If all assumptions are met, if this indeed has all value bits set, but not the sign bit, then this is the highest value representable in short.
It's possible to get the maximum value more reliably in modern C++ when you know that:
the maximum value for an unsigned type is trivially obtainable
the maximum value for a signed type is assuredly either equal to the maximum value of the corresponding unsigned type, or that value right-shifted until it's in the signed type's range
a conversion of an out-of-range value to a signed type does not have undefined behaviour, but instead gives an implementation-defined value in the signed type's range:
template <typename S, typename U>
constexpr S get_max_value(U u) {
S s = u;
while (s < 0 || s != u)
s = u >>= 1;
return u;
}
constexpr unsigned short USHRT_MAX = -1;
constexpr short SHRT_MAX = get_max_value<short>(USHRT_MAX);
Reformatting a bit:
const CHAR_BIT = 8;
Invalid code in C++, it looks like old C code. Let's assume that const int was meant.
#define BITS(type) (CHAR_BIT * (int)sizeof(type))
Returns the number of bits that a type takes assuming 8-bit bytes, because sizeof returns the number of bytes of the object representation of type.
#define HIBIT(type) ((type) (1 << (BITS(type) - 1)))
Assuming type is a signed integer in two's complement, this would return an integer of that type with the highest bit set. For instance, for a 8-bit integer, you would get 1 << (8 - 1) == 1 << 7 == 0b10000000 == -1.
#define TYPE_MAX(type) ((type) ~HIBIT(type));
The bitwise not of the previous thing, i.e. flips each bit. Following the same example as before, you would get ~0b10000000 == 0b01111111 == 127.
const SHRT_MAX = TYPE_MAX(short);
Again invalid, both in C and C++. In C++ due to the missing int, in C due to the fact that CHAR_BIT is not a constant expression. Let's assume const int. Uses the previous code to get the maximum of the short type.
Taking it one line at a time:
const CHAR_BIT= 8;
Declare and initialize CHAR_BIT as a variable of type const int with
value 8. This works because int is the default type (wrong: see comments below), though it’s
better practice to specify the type.
#define BITS(type) (CHAR_BIT* (int)sizeof(type))
Preprocessor macro, converting a type to the number of bits in that
type. (The asterisk isn’t making anything a pointer, it’s for
multiplication. Would be clearer if the author had put a space before
it.)
#define HIBIT(type) ((type)(1<< (BITS(type)-1)))
Macro, converting a type to a number of that type with the highest bit
set to one and all other bits zero.
#define TYPE_MAX(type) ((type)~HIBIT(type));
Macro, inverting HIBIT so the highest bit is zero and all others are
one. This will be the maximum value of type if it’s a signed type and
the machine uses two’s complement. The semicolon shouldn’t be there, but
it will work in this code.
const SHRT_MAX= TYPE_MAX(short);
Uses the above macros to compute the maximum value of a short.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
In C99, §6.5.3.4:
2 The sizeof operator yields the size (in bytes) of its operand,
which may be an expression or the parenthesized name of a type. ...
4 The value of the result is implementation-defined, and its type (an
unsigned integer type) is size_t, defined in <stddef.h> (and other
headers).
In C++14, §5.3.3:
1 The sizeof operator yields the number of bytes in the object
representation of its operand. ... The result of sizeof applied to any
other fundamental type (3.9.1) is implementation-defined.
The only guaranteed values are sizeof(char), sizeof(unsigned char) and sizeof(signed char) which is one.
However, "the number of bytes in the object representation" seems pretty iron-clad to me. For example, in C99 §6.2.6.1:
4 Values stored in non-bit-field objects of any other object type
consist of n × CHAR_BIT bits, where n is the size of an object
of that type, in bytes. ...
So why is it implementation-defined if it seems pretty defined?
Many of you seem to be misinterpretating my question. I never claimed that:
A) The size of types are defined or the same on all systems,
B) implementation-defined means it can return "random values"
What I'm getting at here is that n * CHAR_BITS is a fixed formula. The formula itself can't changed between implementations. Yes, an int may be 4 bytes or 8 bytes. I get that. But between all implementations, the value must n * CHAR_BITS.
The result of sizeof is implementation defined because the size of the various basic types are implementation defined. The only guarantees we have on the size of the types in C++ is that
sizeof(char) = 1 and sizeof(char) <= sizeof(short) <= sizeof(int) <=
sizeof(long) <= sizeof(long long)
And that each type has a minimum value it must support C11 [Annex E (informative) Implementation limits]/1
[...]The minimum magnitudes shown shall be replaced by implementation-defined magnitudes with the same sign.[...]
#define CHAR_BIT 8
#define CHAR_MAX UCHAR_MAX or SCHAR_MAX
#define CHAR_MIN 0 or SCHAR_MIN
#define INT_MAX +32767
#define INT_MIN -32767
#define LONG_MAX +2147483647
#define LONG_MIN -2147483647
#define LLONG_MAX +9223372036854775807
#define LLONG_MIN -9223372036854775807
#define MB_LEN_MAX 1
#define SCHAR_MAX +127
#define SCHAR_MIN -127
#define SHRT_MAX +32767
#define SHRT_MIN -32767
#define UCHAR_MAX 255
#define USHRT_MAX 65535
#define UINT_MAX 65535
#define ULONG_MAX 4294967295
#define ULLONG_MAX 18446744073709551615
So per the standard a int has to be able to store a number that could be stored in 16 bits but it can be bigger and on most of today's systems it is 32 bits.
What I'm getting at here is that n * CHAR_BITS is a fixed formula. The formula itself can't changed between implementations. Yes, an int may be 4 bytes or 8 bytes. I get that. But between all implementations, the value must n * CHAR_BITS.
You are correct but n is defined per C99 §6.2.6.1 as
where n is the size of an object of that type
emphasis mine
So the formula may be fixed but n is not fixed and different implementations on the same system can use a different value of n.
The result of sizeof is not implementation defined. The standard does not say that; it says:
The value of the result is implementation-defined, [...]
That is semantically different. The result of sizeof is well defined:
[...] the size (in bytes) of its operand [...]
Both the bit width of a byte in this context and the number of bytes in non char types is implementation defined.
Because the sizes of basic types are defined in terms of efficiency, not in terms of exact number of bits. An "int" must be something that the CPU can manipulate efficiently. For most modern systems, this quantity turns out to be 32 bits (or 64 bits). For older systems, it was quite often 16 bits. However, if a 35 bits CPU were to exist, an int on such a system would be 35 bits. In other words, C++ does not apply a penalty to enforce a bit-width a CPU might not support at all.
Of course, one could argue that notions of exotic bit widths for basic types have been overtaken by history. I cannot think of any modern CPU that does not support the standard set of 8, 16, and 32 bits (feel free to disagree with this statement, but at least be so kind to give an example!), and 64 bits is also pretty common (and not a big deal to support in software if hardware support is unavailable).
Arguably the C++ language has already moved away from having variable numbers of bits for char; as far as I know, u8"..." converts to char *, but the unicode specification demands that u8 is encoded in 8 bits.
If a char of 8 bits is size 1, then an int of 32 bits is size 4. If a char of 16 bits is size 1, then an int of 32 bits is only size 2. Both situations are equally valid in C++, if such sizes happen to be good choices for their respective hardware.
Padding bits are "unspecified" not "implementation-defined".
Wrong. Very, very wrong. The values of padding bytes are unspecified. The intention here is that the values of these bits may represent trap values, but not necessarily.
The standard tells you sizeof returns bytes * CHAR_BITS, but doesn't specify a size (other than the exact-width types). The number of bytes a type occupies is implementation-defined, hence sizeof must be as well.
Implementation-defined is decribed as:
unspecified value where each implementation documents how the choice
is made
When you declare a new variable in example like this:
size_t a;
it will be equal with this:
unsigned short int a; // unsigned short a
On 32-bit computers size of the integer number (int) is 4 bytes.
Size of the short int is 2 bytes.
In C programming languange 'size_t' is the return type of the 'sizeof()' operator.When you use 'sizeof()' operator he will give you the size of the object.Argument of the 'sizeof()' must be an l-value type. Size of the element(object) cannot be a negative number and it must be an integer.
This declaration compiles without warnings in g++ -pedantic -Wall (version 4.6.3):
std::size_t foo = -42;
Less visibly bogus is declaring a function with a size_t argument, and calling it with a negative value. Can such a function protect against an inadvertent negative argument (which appears as umpteen quintillion, obeying §4.7/2)?
Incomplete answers:
Just changing size_t to (signed) long discards the semantics and other advantages of size_t.
Changing it to ssize_t is merely POSIX, not Standard.
Changing it to ptrdiff_t is brittle and sometimes broken.
Testing for huge values (high-order bit set, etc) is arbitrary.
The problem with issuing a warning for this is that it's not undefined behavior according to the standard. If you convert a signed value to an unsigned type of the same size (or larger), you can later convert that back to a signed value of the original signed type and get the original value1 on any standards-compliant compiler.
In addition, using negative values converted to size_t is fairly common practice for various error conditions -- many system calls return an unsigned (size_t or off_t) value for success or a -1 (converted to unsigned) for an error. So adding such a warning to the compiler would cause spurious warnings for much existing code. POSIX attempts to codify this with ssize_t, but that breaks calls that may be successful with a return value greater than the maximum signed value for ssize_t.
1"original value" here actually means "a bit pattern that compares as equal to the original bit pattern when compared as that signed type" -- padding bits might not be preserved, and if the signed representation has redundant encodings (eg, -0 and +0 in a sign-magnitude representation) it might be 'canonicalized'
The following excerpt is from a private library.
#include <limits.h>
#if __STDC__ == 1 && __STDC_VERSION__ >= 199901L || \
defined __GNUC__ || defined _MSC_VER
/* Has long long. */
#ifdef __GNUC__
#define CORE_1ULL __extension__ 1ULL
#else
#define CORE_1ULL 1ULL
#endif
#define CORE_IS_POS(x) ((x) && ((x) & CORE_1ULL << (sizeof (x)*CHAR_BIT - 1)) == 0)
#define CORE_IS_NEG(x) (((x) & CORE_1ULL << (sizeof (x)*CHAR_BIT - 1)) != 0)
#else
#define CORE_IS_POS(x) ((x) && ((x) & 1UL << (sizeof (x)*CHAR_BIT - 1)) == 0)
#define CORE_IS_NEG(x) (((x) & 1UL << (sizeof (x)*CHAR_BIT - 1)) != 0)
#endif
#define CORE_IS_ZPOS(x) (!(x) || CORE_IS_POS(x))
#define CORE_IS_ZNEG(x) (!(x) || CORE_IS_NEG(x))
This should work with all unsigned types.
Ok this might sound a little vague from the title, but that's because I have no idea how to word it differently. I'll try to explain what I mean: very often in certain libraries, the 'init' function accepts some parameters, but that parameter then accepts multiple parameters (right..). An example, would be like this:
apiHeader.h
#define API_FULLSCREEN 0x10003003
#define API_NO_DELAY 0x10003004
#define API_BLAH_BLAH 0x10003005
main.c:
apiInit(0, 10, 10, 2, API_FULLSCREEN | API_NO_DELAY | API_BLAH_BLAH);
How does this work? I can't find the answer anywhere, most likely because I don't know how it's actually called so I have no clue what to search for. It would be very useful in my current project.
Thanks in advance!
The parameter is usually called "$FOO flags" and the values are or-ed. The point is that the parameter is a numeric type that is constructed as the bitwise or of multiple possible values.
In the processing functions, the values are usually tested with a bitwise and:
if ( (flags & API_FULLSCREEN) != 0 )
You have to be careful to assign values in a way that keeps the OR operation linear. In other words, don't set the same bit in two different or-able values, like you did in your header. For example,
#define API_FULLSCREEN 0x1
#define API_NO_DELAY 0x2
#define API_BLAH_BLAH 0x4
works and allows you to deconstruct all combinations of flags in your function, but
#define API_FULLSCREEN 0x1
#define API_NO_DELAY 0x2
#define API_BLAH_BLAH 0x3
does not because API_FULLSCREEN | API_NO_DELAY == API_BLAH_BLAH.
Viewing from a higher level, a flags int is a poor man's variable argument list. If you consider C++, you should encapsulate such detail in a class or at least a std::bitset.
This fifth parameter is usually a mask. It works by defining several consts (probably an enum) with values that are powers of two, or combinations of them. Then they are encoded into a single value using |, and decoded using &. Example:
#define COLOUR_RED 0x01
#define COLOUR_GREEN 0x02
#define COLOUR_BLUE 0x04
#define COLOUR_CYAN (COLOUR_BLUE | COLOUR_GREEN) // 0x06
// Encoding
SetColour(COLOUR_RED | COLOUR_BLUE); // Parameter is 0x05
// Decoding
void SetColour(int colour)
{
if (colour & COLOUR_RED) // If the mask contains COLOUR_RED
// Do whatever
if (colour & COLOUR_BLUE) // If the mask contains COLOUR_BLUE
// Do whatever
// ..
}
What they are doing there is using binary OR to combine the flags together.
so what is actually happening is:
0x10003003 | 0x10003004 | 0x10003005 == 0x10003007
It's still one parameter, but the 3 flags will combine to create a unique value for that parameter which can be used in the function.
What you are defining as multiple parameter is strictly a single parameter from the function signature point of view.
As for handling multiple Options based on a single parameter, as you can see there is the bitwise Or Operator which sets a single value for the parameter value. The body of the function then uses individual bits to determine the complete settings.
Usually, one bit is allocated for one option and they usually have two state(true/false) values.
The parameter is usually called "flags" and contains an or-ed combination of a set of allowed values.
int flags = API_FULLSCREEN | API_NO_DELAY;
The function can the take this integer parameter and extract the individual items like this:
int fullscreen_set = flags & API_FULLSCREEN;
int no_delay_set = flags & API_NO_DELAY;
int blah_blah_set = flags & API_BLAH_BLAH;
For this to work one has to be carfull in how one chooses the numeric values for the API_* parameters.
Bitwise OR
Bitwise OR works almost exactly the same way as bitwise AND. The only difference is that only one of the two bits needs to be a 1 for that position's bit in the result to be 1. (If both bits are a 1, the result will also have a 1 in that position.) The symbol is a pipe: |. Again, this is similar to boolean logical operator, which is ||.
01001000 | 10111000 = 11111000
and consequently
72 | 184 = 248
So In you Method not a multiple parameter it is actully one parameter.
you can use Bitwise OR opearation on API_FULLSCREEN | API_NO_DELAY | API_BLAH_BLAH and passed it in method.
The example that you gave will not work as expected. What you do is to use a particular bit for a particular option - and the OR combines then
Example
#define OPT1 1
#define OPT2 2
#define OPT3 4
So bit 1 is for OPT1, bit 2 is for OPT2 etc.
So OPT1 | OPT3 sets bit 1 and 3 and gives a value of 5
In the function you can test if a particular option is required using the AND operator
So
void perform(int opts)
{
if (opts & OPT1)
{
// Do stuff for OPT1
}
...
The value of these parameters are defined in a way that they don't have any overlap. Something like this:
#define A 0x01
#define B 0x02
#define C 0x04
#define D 0x08
Given the above definitions, your can always determine which of the above variables have been ORed using the bitwise AND operator:
void foo(int param)
{
if(param & A)
{
// then you know that A has been included in the param
}
if(param & B)
{
// then you know that B has been included in the param
}
...
}
int main()
{
foo (A | C);
return 0;
}