This is a language-independent question, though I've tagged with languages just to give some tags relevant to the code samples I'm posting below. I'm somewhat new to programming. In various languages I've seen functions that have parameters separated by what I think is the bitwise OR operator. I've used these functions without understanding exactly how the parameters work.
I'll give some examples in case you're not sure what I'm talking about.
From http://www.php.net/manual/en/function.error-reporting.php:
<?php
// Turn off all error reporting
error_reporting(0);
// Report simple running errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);
// Reporting E_NOTICE can be good too (to report uninitialized
// variables or catch variable name misspellings ...)
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
// Report all errors except E_NOTICE
error_reporting(E_ALL & ~E_NOTICE);
// Report all PHP errors (see changelog)
error_reporting(E_ALL);
// Report all PHP errors
error_reporting(-1);
// Same as error_reporting(E_ALL);
ini_set('error_reporting', E_ALL);
?>
From http://www.cplusplus.com/doc/tutorial/files/:
ofstream myfile ("example.bin", ios::out | ios::app | ios::binary);
What exactly is the deal with functions that take parameters like that? Can someone explain?
If you lookup what those constants are, you'll see they'll be like this: 1, 2, 4, 8, 16, etc.
So by adding them all together basically, (what the bitwise does AFAIK from this: "Bit shifting in PHP is arithmetic.") you get a new "number".
http://us2.php.net/manual/en/language.operators.bitwise.php
The manual page has a lot of good info on how it works.
So basically to answer the question of how that function works, it is accepting one integer, and the bitwise operator is doing the "math" and turning those three constants into one new number.
var_dump(E_ERROR);
var_dump(E_WARNING);
var_dump(E_PARSE);
var_dump(E_ERROR | E_WARNING | E_PARSE);
int(1)
int(2)
int(4)
int(7)
So it's the same as:
error_reporting(7);
The same thing as a + b + c. It's just an expression, with
the | (bitwise or) operator.
These are predefined constants, whose values are combined to produce a bit field.
You can use decbin() in PHP to give an insight into how these constants work. decbin produces a string which shows the binary representation of the number.
printf("%02s", decbin(E_ERROR)); // output 01
printf("%02s", decbin(E_WARNING)); // output 10
printf("%02s", decbin(E_ERROR | E_WARNING)); // output 11
(I padded all the values so that the OR operation is clear)
You're passing a single number to the function, whose value represents the options you want to enable. In the function, the options could be extracted using bitwise &:
function func($flag) {
if ($flag & E_ERROR) echo "E_ERROR enabled";
// etc.
}
These are flags. Sometimes a function receives multiple indications on how to operate, such as whether to open the file in binary mode, or in read-only mode, etc... This modes are not mutually exclusive - file can be opened for reading in both text and binary mode, or for writing in both text and binary mode. So you need to be able to specify both options together if you want.
One simple way to achieve this is with bit flags. You have one integer number that holds all the flags. The least significant bit says, for example, if the file is to be opened in text mode (0 - text, 1 - binary), the second bit from the right says whether to open for read or write, etc...
To implement this you use constants:
BINARY = 1
WRITE = 2
Now, if you want to open in both binary and write mode, you use BINARY | WRITE - which results in 3.
The called function then breaks the number back into bits:
isBinary = (flags & BINARY) != 0;
isWriteMode = (flags % WRITE) != 0;
I think
// Report simple running errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);
is equivalent to the following in C or C++
// Report simple running errors
int const error_filter = E_ERROR | E_WARNING | E_PARSE;
error_reporting( error_filter );
Most probably, the symbols E_ERROR, E_WARNING are numbers with a single bit set, such as for example
E_ERROR = 00000001
E_WARNING = 00000010
E_PARSE = 00000100
So, a bitwise-OR of them returns a number with the bit set in all of those positions
error_filter = E_ERROR | E_WARNING | E_PARSE = 00000111
One tricky thing is the type of error_filter, I wrote int but that may not be pedantically correct. One can say uint32_t. Another alternative is to leave the type altogether as in the original code.
Related
So when I currently view phpinfo() in PHP, my error_reporting is set to some number, which represents the sum of all the error constant values, right?
Let's say, I accidentally set the value of error_reporting to some weird value by accident in .htaccess for example:
-1
Value that is bigger than E_ALL (32768 for example, if I'm correct)
When setting it with a string, I do a typo (**E_AL** & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED) - typo in E_ALL
What would happen, would it be set to some default value? Or from php.ini? I tried setting all the values above and they all were set in the Local Value without any problems.
I'm curious what will happen with any other value as well, will it default to php.ini or what?
Thanks!
PHP uses bitwise operators to determine whether the error level should be reported.. so whatever your integers value is as binary it would bitwise & to see if the error is reported.
E.g.
if E_DEPRECATED were (not saying this is accurate): 01, E_WARNING is 10, E_NOTICE is 100, using E_DEPRECATED | E_WARNING | E_NOTICE would give the binary 111, thus when an error is reported, like E_WARNING, it would take the value set, and bitwise & it to determine whether the report is displayed:
111 & 010 = True, so the error would be reported.
if you just used E_DEPRECATED | E_NOTICE, the binary is 101, so 101 & 010 = False, so the error won't be reported.
Each of these binaries can be converted to base10, 01 = 1, 10 = 2, 100 = 4 etc.
So if you were curious as to which errors would be reported with your random integer you can do:
int & E_WARNING in your PHP parser, if its True then the error will be shown, if its FALSE then the error will be ignored.
This is a good convention to learn, as its very useful when implementing logging on your application too, you can use the same system, and so you don't have to implement a long switch or if .. elseif .. block to determine whether a log level should be logged or not according to config.
/**
* Determines whether this message should be logged based on the provided type and the set threshold
* #access protected
* #param int $type
* #param string $name name of the log to check.
* #return boolean
*/
protected function should_log($type,$name='default') {
return (bool) ($this->getConfig($name)->threshold & $type);
}
so the threshold would be a binary number in your config (which uses constants for readability) then it bitwises & against the provided log type which returns True or False to determine whether to log the message to the logger by name $name... much more optimised.
I would like to store user rights as integer in database, but not sure how... How does it work on PHP with for example error_reporting() ?
You got different constants, like... E_ERROR = 1, E_WARNING = 2, E_PARSE = 4, E_NOTICE = 8 etc... and you can set it like error_reporting(E_ERROR | E_NOTICE) ...
In this case E_WARNING | E_NOTICE == 10.
Ok, so I do understand that this is binary operation "OR" and as far as consecutive constants are multiplied by 2, everything should be reversable... but how?
So I got this (int)10. And how do I check that it is E_WARNING and E_NOTICE?
PS. I do understand that it is 1010 on binary notation.
If you want to check if values are set, you can use the bitwise AND & operator.
$warningEnabled = $val & E_WARNING;
This works because (assume $val is 128)...
1000 0000 & # $value
0000 0010 # E_WARNING
Since the same bit isn't set in both, you can tell that $val doesn't have warnings set.
You can execute this in PHP if you like with bindec() function (wrap the above values as strings), it may help you understand better.
If you want to know if the value contains E_WARNING, do:
if ($value & E_WARNING)
I would like to understand the following code from Zenphoto’s plugin:
$plugin_is_filter = 5|ADMIN_PLUGIN|THEME_PLUGIN;
The snippet was disjointed from context. It is just about the Idea behind it.
Are 5|ADMIN_PLUGIN|THEME_PLUGIN Permissions using bitwise?
When it is useful to use?
Thanks for any hint, links.
Bitfields are useful when you need to provide a set of boolean options in one variable. For example, PHP lets you set your error reporting like this:
error_reporting(E_ERROR | E_WARNING | E_PARSE);
In binary, those constants have these values:
E_ERROR 0001
E_WARNING 0010
E_PARSE 0100
If you OR a set of options like that together, you'll be able to express the settings in one field:
E_ERROR | E_WARNING | E_PARSE 0111
Then, you can check for an option being set using AND:
if ($option & E_ERROR === E_ERROR) {
// E_ERROR is set, do something
}
Yes, that is an example of bitwise OR.
You typically use bitwise operations when you're interested in packing multiple boolean flags into a single integer. Bitwise operators allow you to manipulate the individual bits of a byte, meaning an 8 bit byte can be used to store 8 distinct boolean values. It's a technique which was useful when using a whole 8 bit byte to store a single binary "yes" or "no" was considered wasteful.
Today, there is virtually no reason to ever prefer using this kind of bitpacking in PHP (especially with a magic number like that 5) over a simple configuration array. It is a technique which adds virtually nothing of value to PHP code, increasing complexity and decreasing maintainability for no real gain. I would be very skeptical of any new PHP code produced which makes use of bitwise flags in this way.
The variable $plugin_is_filter is being used to flag which plugins to load. Essentially, it is being treated like an array bits that correspond to an enumerated set plugins. For more information, see the links below.
This explains what ADMIN_PLUGIN and THEME_PLUGIN are.
Search the page for '$plugin_is_filter' to get a brief explanation of how to use this variable.
http://www.zenphoto.org/news/zenphoto-plugin-architecture
I hope this helps.
Trying to understand this entry in the php manual on debug_backtrace.
I don't understand what they mean by "this parameter is a bitmask for ...."
I have done web searches on bitmasks and my head is spinning round so I have decided I don't really want to learn the detail about it but just to know how I can supposed to add the options to that function.
Do I put in both options as in
debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, DEBUG_BACKTRACE_IGNORE_ARGS)
if I want both and one of them if I only want that one?
Be aware that those 2 constants (DEBUG_BACKTRACE_PROVIDE_OBJECT, DEBUG_BACKTRACE_IGNORE_ARGS) are different in meaning. While DEBUG_BACKTRACE_PROVIDE_OBJECT provides an additional object when present, DEBUG_BACKTRACE_IGNORE_ARGS strips the args when present.
Since the most common use-case for these constants is to reduce memory usage, the way with least memory-consumption is:
debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
NOT
// false friend!
debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS);
It overrides the default of DEBUG_BACKTRACE_PROVIDE_OBJECT and additionally ignores DEBUG_BACKTRACE_IGNORE_ARGS.
The constants will have values of 2^n in decimal, or (10)^n in binary. For example - 1, 10, 100, 1000, etc (in binary).
Say a=001, b=010, c=100:
You can do bitwise or on, for example, a and b. This will mean each bit will be 'turned on' if the same bit in either a or b is 'on'.
a | b == 011
This is a bitmask. The bitmask is checked for the inclusion of a by
bitmask & a != 0
Which is
011 & 001 == 001 != 0
However, because c is not in the bitmask:
bitmask & c == 011 & 100 == 0
So, to include both a and b in the bitmask, you use the binary or operator.
debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS);
It means you combine options with the bitwise OR operator: |.
For example:
debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS);
For more details about bitmasks: http://en.wikipedia.org/wiki/Mask_(computing)
I see that in PHP there are functions that can accept multiple options into a single argument, for example:
error_reporting(E_ERROR & E_WARNING);
I want to implement this kind of functionality into my javascript function. Do you know examples of functions that take this kind of arguments?
I'm totally confused about how does the function know what are the options that are passed...
(Assume it is instead: error_reporting(E_ERROR | E_WARNING); )
Well, it is a bitmask. So E_ERROR might be a number like this (in binary):
0010000
and E_WARNING might be:
0000010
and when they are combined with |, you get
0010010
(a single integer, with multiple bits set)
The function can then check which bits are set using the & bitwise operator. You can certainly do it in javascript, although it might be less common, and possibly less efficient and reliable as the numbers get bigger since javascript doesn't really have integers, they are really floating point numbers.
In javascript, you might prefer to use something like this:
error_reporting({warning: true, error: true});
(edited to show it in the more sensible way, with | not & to combine them)
Yes, it's possible, but it works with |.
var flag1 = 1,
flag2 = 2; // powers of 2
function get(flags) {
if((flags & flag1) === flag1) { // remove all other bits and check
alert('flag1'); // whether you get the flag itself
}
if((flags & flag2) === flag2) {
alert('flag2');
}
}
get(flag1 | flag2); // alerts both
You could of course create a helper function which does the chekcing so that you don't need those parentheses:
function contains(flags, flag) {
return (flags & flag) === flag;
}
http://jsfiddle.net/pimvdb/NpFYj/1/