Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I recently corrected a bug in a C program where I had:
if (foobar != FOO | BAR | BAZ)
The correct code is
if (foobar != (FOO | BAR | BAZ))
According to the C operator precedence it is clear that != has precedence over |.
My question is why it is like this and not the other way around? From my experience I will often use either a == b || a == c or d == (a | b | c), but never a == b | c == d.
What is the logic behind this choice?
It has historical reasons, quote from Dennis Ritchie:
“Early C had no separate operators for & and && or | and ||. Instead
it used the notion (inherited from B and BCPL) of ‘truth-value
context': where a Boolean value was expected, after ‘if‘ and ‘while‘
and so forth; the & and | operators were interpreted as && and || are
now; in ordinary expressions, the bit-wise interpretations were used.
It worked out pretty well, but was hard to explain. (There was the
notion of ‘top-level operators’ in a truth-value context.) “The
precedence of & and | were as they are now.
Primarily at the urging of
Alan Snyder, the && and || operators were added. This successfully
separated the concepts of bit-wise operations and short-circuit
Boolean evaluation. However, I had cold feet about the precedence
problems. For example, there were lots of programs with things like:
if (a==b & c==d) …
“In retrospect it would have been better to go
ahead and change the precedence of & to higher than ==, but it seemed
safer just to split & and && without moving & past an existing
operator.”
Dennis Ritchie's Development of the C Language covers this and other curious historical artifacts.
Basically, originally the language did not have the && and || operators -- just & and |, so you would write things like a == b | c == d. The precedence rules were designed based on that.
Later, the short ciruiting operators were added, but the precedence of the old operators was not revised.
Related
for (i in 1:length(data$name)){
if (!is.na(data$years[i]) >= 34 & !is.na(data$gender[i]) == "male" & !is.na(data$classification[i]) == "mid"){
print(data$name)
}
}
There's a few problems in your code. I am assuming this is a class exercise or similar, so I'll add a bit extra detail to illustrate where you've missed a step.
First of all you loop works fine, but your if condition is not completely correct.
!is.na(data$years[i]) >= 34
All of your conditions look (somewhat) like this. The idea is obvious, you want to "check that data$years[i] is not null, and above 34". But in R (and most languages) you have to check these seperately.
!is.na(data$years[i]) && data$years[i] >= 34
Similar for the rest of your conditions.
Next your print statement is printing out everything, because this is what you're asking it to:
print(data$name)
is "ignorant" of anything else you've done up till now. It seems you want to print the specific record, eg:
print(data$name[i])
And this is the way to go about it.
Now R has a thing called "vectorization", so we could wrap this entire loop up in one go:
data$name[!is.na(data$years) & !is.na(data$gender) & !is.na(data$classification) & data$year > 34 & data$gender == "male" & data$classification == "mid"]
But I am assuming that is not part of your current exercise. Note the slight (but important) difference that for vectorized (eg. more than 1) condition I use single & but for single conditions I use 2 &&. The latter is optimized to be "lazy" for single inputs (thus faster).
Perhaps you can try subset + complete.cases like below
subset(
data,
years >= 34 & gender == "male" & classification == "mid" & complete.cases(data[c("years", "gender", "classification")])
)$name
This question already has answers here:
Using Exclamation Marks '!' in C
(5 answers)
Closed 3 years ago.
I was reading a code and I found these "!" all over the place what is it supposed to do ? this is a part from the code I found it in :
if (!piocherMot(motSecret))
exit(0);
piocherMot is a function in another file while "motsecret" is a variable in my main code.
This
!
is logical NOT operator & its a unary operator i.e it takes only one operand, result of this operator is either true(1) or false(0). Truth table of logical NOT operator is
A !A
----------
| 0 | 1 |
| 1 | 0 |
----------
Hence if piocherMot(motSecret) results in true i.e !1 which is 0 then if block will not get executes, in reverse case it gets executes.
if(!1) { /* 0 i.e if block won't executes */
}
And
if(!0) { /* 1 i.e if blocks executes */
}
I found this code on ioccc and I have trouble even beginning to understand how it works!
void main(int riguing, char** acters) {
puts(1[acters-~!(*(int*)1[acters]%4796%275%riguing)]);
}
An explanation of how this is valid code and how it actually works would be fantastic!
First, in C (and C++) k[pointer] and pointer[k] mean exactly the same thing, which is *(k + pointer) and *(pointer + k), respectively. Code obfuscators often seem to like to use the first version because many people find it unusual. But it's reasonably obvious that pointer + k and k + pointer are the same computation.
The other little diversion in the snippet is the use of
pointer-~!(something)
which is exactly the same as
pointer + (something == 0 ? 2 : 1)
How this works:
The ! operator turns any true (non-zero) value into 0 and the false (0) value into a boolean true (1):
!something: something == 0 ? 1 : 0
The ~ operator is bitwise inverse, so it turns 0 into the number consisting of all 1 bits, which is -1 and 1 into the number consisting of all 1 bits except the last bit, which is -2. See Wikipedia article on two's complement.
~!something: something == 0 ? -2 : -1
Subtracting that from something is the same as adding the negative (a - -b == a + b)
a-~!something: something == 0 ? a + 2 : a + 1
Finally
1[a-~!something]: something == 0 ? a[3] : a[2]
So it selects either the second or third command line argument based on whether some computation is zero or not.
So now we need to decipher "some computation". We start with the type-punning operator *(T *)(pointer), in this case *(int*)(char*), reads out whatever the pointer points to as though it were a T. So in this case, it reads the first sizeof(int) characters from 1[acters] -- that is, from the first command-line argument (argv[1]) -- as though they were the internal representation of an integer. That will code every president as an integer based on the first four characters of their surname.
While there have been several repeated presidential surnames in US history, it's not a problem as long as the two presidents with the same name shared a political party.
One such pair, the father and son John Adams, Jr. (a Federalist), and John Quincy Adams (elected to the senate as a Federalist and to the presidency as a Democratic-Republican), are eliminated as being prior to the first valid president (Franklin Pierce), as is the elder Harrison (William Henry, a Whig) whose grandson Benjamin was elected as a Republican. The father and son George H.W. and George W. Bush are both Republicans. And the two Johnsons, Andrew and Lyndon Baines (as far as I know, not related to each other), were both Democrats.
So that leaves only the two Roosevelts, Theodore (Republican) and Franklin Delano (Democrat). The great-great-great-great-grandfathers of the two Roosevelt presidents were the brothers Johannes and Jacobus, sons of Nicholas Roosevelt (or Nicholas van Rosenvelt) (1658-1742) and grandsons of the Dutch immigrant Claes Maartenszen Van Rosenvelt, making them fifth cousins. However, the presidents were more closely related to each other through Eleanor Roosevelt, Theodore's niece and FDR's wife. In order for the IOCCC entry to work, it's necessary to represent the younger Roosevelt as "fdr", as he was commonly known.
So that only leaves (integer)%4796%275%riguing, or (integer)%4796%275%4, since riguing (aka argc) is 4. That's a simple hash function, which I imagine was discovered by trial and error using the list of presidential surnames and their affiliations.
I'm developing a domain specific language. Part of the language is exactly like C expression parsing semantics such as precidence and symbols.
I'm using the Lemon parser. I ran into an issue of the same token being used for two different things, and I can't tell the difference in the lexer. The ampersand (&) symbol is used for both 'bitwise and' and "address of".
At first I thought it was a trivial issue, until I realized that they don't have the same associativity.
How do I give the same token two different associativities? Should I just use AMP (as in ampersand) and make the addressof and bitwise and rules use AMP, or should I use different tokens (such as ADDRESSOF and BITWISE_AND). If I do use separate symbols, how am I supposed to know which one from the lexer (it can't know without being a parser itself!).
If you're going to write the rules out explicitly, using a different non-terminal for every "precedence" level, then you do not need to declare precedence at all, and you should not do so.
Lemon, like all yacc-derivatives, uses precedence declarations to remove ambiguities from ambiguous grammars. The particular ambiguous grammar referred to is this one:
expression: expression '+' expression
| expression '*' expression
| '&' expression
| ... etc, etc.
In that case, every alternative leads to a shift-reduce conflict. If your parser generator didn't have precedence rules, or you wanted to be precise, you'd have to write that as an unambiguous grammar (which is what you've done):
term: ID | NUMBER | '(' expression ')' ;
postfix_expr: term | term '[' expression '] | ... ;
unary_expr: postfix_expr | '&' unary_expr | '*' unary_expr | ... ;
multiplicative_expr: unary_expr | multiplicative_expr '*' postfix_expr | ... ;
additive_expr: multiplicative_expr | additive_expr '+' multiplicative_expr | ... ;
...
assignment_expr: conditional_expr | unary_expr '=' assignment_expr | ...;
expression: assignment_expr ;
[1]
Note that the unambiguous grammar even shows left-associative (multiplicative and additive, above), and right-associative (assignment, although it's a bit weird, see below). So there are really no ambiguities.
Now, the precedence declarations (%left, %right, etc.) are only used to disambiguate. If there are no ambiguities, the declarations are ignored. The parser generator does not even check that they reflect the grammar. (In fact, many grammars cannot be expressed as this kind of precedence relationship.)
Consequently, it's a really bad idea to include precedence declarations if the grammar is unambiguous. They might be completely wrong, and mislead anyone who reads the grammar. Changing them will not affect the way the language is parsed, which might mislead anyone who wants to edit the grammar.
There is at least some question about whether it's better to use an ambiguous grammar with precedence rules or to use an unambiguous grammar. In the case of C-like languages, whose grammar cannot be expressed with a simple precedence list, it's probably better to just use the unambiguous grammar. However, unambiguous grammars have a lot more states and may make parsing slightly slower, unless the parser generator is able to optimize away the unit-reductions (all of the first alternatives in the above grammar, where each expression-type might just be the previous expression-type without affecting the AST; each of these productions needs to be reduced, although it's mostly a no-op, and many parser generators will insert some code.)
The reason C cannot simply be expressed as a precedence relationship is precisely the assignment operator. Consider:
a = 4 + b = c + 4;
This doesn't parse because in assignment-expression, the assignment operator can only apply on the left to a unary-expression. This doesn't reflect either possible numeric precedence between + and =. [2]
If + were of higher precedence than =, the expression would parse as:
a = ((4 + b) = (c + 4));
and if + were lower precedence, it would parse as
(a = 4) + (b = (c + 4));
[1] I just realized that I left out cast_expression but I can't be cast to put it back in; you get the idea)
[2] Description fixed.
Later I realized I had the same ambiguity between dereference (*) and multiplication, also (*).
Lemon provides a way to assign a precidence to a rule, using the name used in the associativity declarations (%left/right/nonassoc) in square brackets after the period.
I haven't verified that this works correctly yet, but I think you can do this (note the things in square brackets near the end):
.
.
.
%left COMMA.
%right QUESTION ASSIGN
ADD_ASSIGN SUB_ASSIGN MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN
LSH_ASSIGN RSH_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN.
%left LOGICAL_OR.
%left LOGICAL_AND.
%left BITWISE_OR.
%left BITWISE_XOR.
%left BITWISE_AND.
%left EQ NE.
%left LT LE GT GE.
%left LSHIFT RSHIFT.
%left PLUS MINUS.
%left TIMES DIVIDE MOD.
//%left MEMBER_INDIRECT ->* .*
%right INCREMENT DECREMENT CALL INDEX DOT INDIRECT ADDRESSOF DEREFERENCE.
.
.
.
multiplicative_expr ::= cast_expr.
multiplicative_expr(A) ::= multiplicative_expr(B) STAR cast_expr(C). [TIMES]
{ A = Node_2_Op(Op_Mul, B, C); }
.
.
.
unary_expr(A) ::= STAR unary_expr(B). [DEREFERENCE]
{ A = Node_1_Op(Op_Dereference, B); }
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 12 years ago.
Someone showed me the following code snippet and asked what it meant:
if (!pFCT->FBMap(| ( VBQNum - 1 ) / 8 |) & (1 << (7 - ( ( VBQNum - 1 ) % 8)))))
{
stuff
}
And I got stuck on the stand alone vertical bars. I know two together mean "or" but just one, what does that mean.
One bar by itself means "bitwise OR" (as opposed to the double bar which means "Logical OR")
1 | 1 == 1
0 | 1 == 1
1 | 0 == 1
0 | 0 == 0
true || true == true
false || true == true
01 | 10 == 11
01 || 10 == true
However, the vertical bars in your sample, as far as I can tell, are syntax errors. It looks like the author is going for "absolute value", which would use vertical bars – in writing or pseudo-code – but not in any computer language I know of.
if (!pFCT->FBMap(| ( VBQNum - 1 ) / 8 |) & (1 << (7 - ( ( VBQNum - 1 ) % 8))))) { stuff }
/* ^^^ syntax error ^^^ */
I guess whoever showed you the line in question meant absolute value
if (!pFCT->FBMap(abs( ( VBQNum - 1 ) / 8 )) & (1 << (7 - ( ( VBQNum - 1 ) % 8))))) { stuff }
/* ^^^^^^ ^^^ */
Oh! A single vertical bar means bitwise or.
Bitwise inclusive or:
The bitwise-inclusive-OR operator compares each bit of its first operand to the corresponding bit of its second operand. If either bit is 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to 0.
Source.
It is a bitwise OR.
Essentially it takes the two values and ORs each of the corresponding bits in their binary representations:
10010001
01001010
--------
11011011
If either operand's bit is a 1, the answer's bit in that place is a one. If neither are 1s, the answer has a 0 there.
It is a bitwise OR operator.
Dale said he knew it meant "or" with two operands. His question is what it means when used as a unary operator. Short answer is that it doesn't mean anything in C/C++.
In some languages (like Verilog for coding hardware) this is an or-reduction, which result in a 1 if any bit is one.
So I think this is a syntax error unless the is something funny going on overloading the parentheses that I can't get my head around.
Your code is not valid C, unless put in a specific (and quite artificial) context. Operator | is a binary operator. It is a bitwise-or, as you seem to know already. By itself, it cannot be used the way it is used in your code.
If one wanted to force this code to compile as C code, one'd probably have to define FBMap as a macro. Something like
#define FBMap(x) something_else(abs(0 x 0))
thus trying to emulate the mathematical "absolute value" operator | |. Your call will expand into
pFCT->something_else(abs(0 | ( VBQNum - 1 ) / 8 | 0))
thus making the application of | operator valid.
But even after that you'd need something_else to be a function pointer in that *pFCT struct, since the call looks awfully as a C++ method call. Your question is tagged C, so the only way to make it work in C is to introduce a function pointer member into the struct.