If I do *ptr[x], is that equivalent to *(ptr[x]), or (*ptr)[x]?
*(ptr[x])
See the Wikipedia operator precedence table, or, for a more detailed table, this C/C++ specific table.
In C, all postfix operators have higher precedence than prefix operators, and prefix operators have higher precedence than infix operators. So its *(ptr[x])
Using the counter-clockwise movement of analyzing and parsing that simple example
1. starting with ptr, work in counter-clockwise until you hit asterisk operator
2. asterisk, in counter-clockwise until you hit subscript operator
3. we arrive here, at subscript operator [x]
Since [] has higher precedence than the asterisk as per this table , that makes it *(ptr[x])
Related
Consider the below question in regard to this expression: (a+b)+ (c +(d+e)) +(f+g)
In C we use precedence and associativity to decide which operator should be evaluated first and if there is more than one operator with the same precedence, then in what order they should be associated.
My question is:
Is (d+e) evaluated first by the compiler as it is the innermost nested parenthesis in the expression?
If so, do associativity and precedence somehow recommend innermost parenthesis evaluation should be done first?
I strongly feel that it doesn't, and if it doesn't then why would the compiler even decide to evaluate the innermost parenthesis first? Because going from left to right and evaluating parentheses at the same level seems much more logical to me.
You are confusing operator precedence with order of evaluation. These are different though related terms. See What is the difference between operator precedence and order of evaluation?
Specifically:
Do (d+e) is evaluated first by compiler as it is innermost nested parenthesis in the expression?
This depends on the order of evaluation of the + (additive) operators, nothing else. The order is unspecified for + (as it is for most operators) and we can't know it, nor should we rely on it. Compilers are allowed to do as they please and don't need to tell you (document) how and when they pick a certain order.
If so does associativity and precedence somehow explains innermost parenthesis evaluation should be done first?
No, this has nothing to do with operator precedence.
I strongly feel that it doesn't and if it don't then why we decided to evaluate innermost parenthesis first, because going from left to right and evaluating parenthesis at same level seems much logical to me
See 1)
Consider instead
(a() + b()) + (c() + (d() + e())) + (f() + g())
where each of the functions prints it's letter and, of course, returns a value
int a(void) { putchar('a'); return 42; }
When that expression is evaluated, something like "abcdefg" will be printed according to "order of evaluation", regardless of the operator precedence.
The order of evaluation is not something the Standard has rules for. Each compiler implementation can do the evaluation as it likes best ... even changing the order between compilations or runs.
While at least from a hand wave point of view I believe I know what an "arithmetic operator" is, I'm looking for a formal definition. I've examined the C17 standard document and I can't find such a definition, although it uses the term "arithmetic operator" in several places.
The closest I've been able to find is in the index of C17, where page numbers are provided for additive, bitwise, increment and decrement, multiplicative, shift, and unary under the common heading "arithmetic operators". I've looked online at various sources and the most common thing I've found only says that binary +, -, *, /, and % are the C arithmetic operators. Some also throw in ++ and --.
I'm pretty sure I'm simply missing something since I do find the standard quite daunting. However, I also find the various online sources somewhat dubious since they often seem to differ.
Thanks!
Update: Since some readers objected to my references to both C and C++ in the same posting, I've removed the references to C++ in the modified version above and will do an entirely separate posting for it later if I can first get the issue resolved for C.
The C standard does not explicitly define the term arithmetic operator, though it defines what an arithmetic operand is. If you read carefully, nothing in C is defined by using the term arithmetic operator, it exists only as a grouping in the index and in a title of one section. The term arithmetic operator by itself does not appear in any paragraph.
From the index, we indeed can get a list
arithmetic operators
additive, 6.2.6.2, 6.5.6, G.5.2
bitwise, 6.2.6.2, 6.5.3.3, 6.5.10, 6.5.11, 6.5.12
increment and decrement, 6.5.2.4, 6.5.3.1
multiplicative, 6.2.6.2, 6.5.5, G.5.1
shift, 6.2.6.2, 6.5.7
unary, 6.5.3.3
From this we could formulate that the arithmetic operators are those that require the operands to be arithmetic operands, i.e. of an arithmetic type (except in special cases such as pointer addition, subtraction), i.e.
additive + and -
bitwise &, | and ^
increment and decrement ++ and --
multiplicative *, / and %
shift << and >>
unary -, ~ and +. It is debatable whether ! is an arithmetic operator or not, even though it is listed in section 6.5.3.3.
Another notable thing about these operators are that the operands might undergo usual arithmetic conversions.
Arithmatic operators are operators used to perform mathematical operations like addition, substraction, multiplication and division. As simple as that.
ex: a+b = c
Parentheses and pointer symbol have same priority, and they are dealed from left to right. Why does the following code try to get the member nfct from skb, then do the type conversion? It's seems that the associativity is from right to left.
(struct nf_conn *) skb->nfct
I believe the point you're missing here is the Operator Precedence.
The pointer member access operator (->) has higher precedence than the cast.
To elaborate, (borrowed wordings)
Operator precedence determines which operator is performed first in an expression with more than one operators with different precedence.
Associativity is used (or comes into play) when two operators of same precedence appear in an expression.
In C (and some other C-like languages) we have 2 unary operators for working with pointers: the dereference operator (*) and the 'address of' operator (&). They are left unary operators, which introduces an uncertainty in order of operations, for example:
*ptr->field
or
*arr[id]
The order of operations is strictly defined by the standard, but from a human perspective, it is confusing. If the * operator was a right unary operator, the order would be obvious and wouldn't require extra parentheses:
ptr*->field vs ptr->field*
and
arr*[id] vs arr[id]*
So is there a good reason why are the operators left unary, instead of right. One thing that comes to mind would be the declaration of types. Left operators stay near the type name (char *a vs char a*), but there are type declarations, which already break this rule, so why bother (char a[num], char (*a)(char), etc).
Obviously, there are some problems with this approach too, like the
val*=2
Which would be either an *= short hand for val = val * 2 or dereference and assign val* = 2.
However this can be easily solved by requiring a white space between the * and = tokens in case of dereferencing. Once again, nothing groundbreaking, since there is a precedent of such a rule (- -a vs --a).
So why are they left instead of right operators?
Edit:
I want to point out, that I asked this question, because many of the weirder aspects of C have interesting explanations, for why they are the way they are, like the existence of the -> operator or the type declarations or the indexing starting from 0. And so on. The reasons may be no longer valid, but they are still interesting in my opinion.
There indeed is an authoritative source: "The Development of the C Language" by the creator of the language, Dennis M. Ritchie:
An accident of syntax contributed to the perceived complexity of the language. The indirection operator, spelled * in C, is syntactically a unary prefix operator, just as in BCPL and B. This works well in simple expressions, but in more complex cases, parentheses are required to direct the parsing. For example, to distinguish indirection through the value returned by a function from calling a function designated by a pointer, one writes *fp() and (*pf)() respectively. The style used in expressions carries through to declarations, so the names might be declared
int *fp();
int (*pf)();
In more ornate but still realistic cases, things become worse:
int *(*pfp)();
is a pointer to a function returning a pointer to an integer. There are two effects occurring. Most important, C has a relatively rich set of ways of describing types (compared, say, with Pascal). Declarations in languages as expressive as C—Algol 68, for example—describe objects equally hard to understand, simply because the objects themselves are complex. A second effect owes to details of the syntax. Declarations in C must be read in an `inside-out' style that many find difficult to grasp [Anderson 80]. Sethi [Sethi 81] observed that many of the nested declarations and expressions would become simpler if the indirection operator had been taken as a postfix operator instead of prefix, but by then it was too late to change.
Thus the reason why * is on the left in C is because it was on the left in B.
B was partially based on BCPL, where the dereferencing operator was !.
This was on the left; the binary ! was an array indexing operator:
a!b
is equivalent to !(a+b).
!a
is the content of the cell whose address is given by a; it can appear on the left of an assignment.
Yet the 50 year old BCPL manual doesn't even contain mentions of the ! operator - instead, the operators were words: unary lv and rv. Since these were understood as if they were functions, it was natural that they preceded the operand; later the longish rv a could then be replaced with syntactic sugar !a.
Many of the current C operator practices can be traced via this route. B alike had a[b] being equivalent to *(a + b) to *(b + a) to b[a] just like in BCPL one could use a!b <=> b!a.
Notice that in B variables were untyped, so certainly similarity with declarations could not have been the reason to use * on the left there.
So the reason for unary * being on the left in C is as boring as "there wasn't any problem in the simpler programs with the unary * being on the left, in the position that everyone was accustomed to have the dereferencing operator in other languages, that no one really thought that some other way would have been better until it was too late to change it".
I just came across that baffles me in MSSQL.
If I do something like:
SELECT 1 | 0 & 0
The output is 0 - I would've thought that the & operator would have a precedence over the |operator.
Any ideas ? Is this a bug or an intended behavior in MSSQL ?
According to SQL Server operator precedence table (SQL2k8+) as #MartinSmith already referenced it in a comment this is how precedence looks like:
Level Operators
1 ~ (Bitwise NOT)
2 * (Multiply), / (Division), % (Modulo)
3 + (Positive), - (Negative), + (Add), (+ Concatenate), - (Subtract), & (Bitwise AND), ^ (Bitwise Exclusive OR), | (Bitwise OR)
4 =, >, <, >=, <=, <>, !=, !>, !< (Comparison operators)
5 NOT
6 AND
7 ALL, ANY, BETWEEN, IN, LIKE, OR, SOME
8 = (Assignment)
When two operators in an expression have the same operator precedence level, they are evaluated left to right based on their position in the expression.
Your issue with bitwise operators
As you can see bitwise operators are all in the same level (3) that's why they're evaluated left to right, so in your example | is evaluated first and then &.
Boolean logical operators are different
These are of course bitwise operators and not logical ones, which would of course evaluate in correct order since AND has level 6 and OR has 7. This means that AND would be evaluated first and OR afterwards.
Brackets are of course the preferred choice for any non trivial expression. In your case it seems trivial, yes, hence brackets weren't used, but since bitwise operators operate on the same level, they must be used when combining at least 3 operands or make sure you order operators in the way you want them to evaluate. In your case:
select 0 & 0 | 1
Would yield correct result.
It hasn't always been this way
Bitwise operator precedence has been equalised since SQL Server 2008. SQL Server 2005 and older had bitwise | (along with exlusive or ^) on a lower level (5), so your expression would evaluate correctly. Why Microsoft decided to put all bitwise operators on the same level is a mystery to me.
It turned out that SQL Books Online were stating invalid real life processing (Thanks to #MartinSmith). So they just updated operator precedence levels documentation page for SQL Server 2008. So apparently this has been working this way for a much longer time (maybe all the time).