Pass operator to function in ML - ml

How can I pass an operator to a function in ML? For example, consider this pseudocode:
function (int a, int b, operator op)
return a op b
Here, an operator can be op +, op -, etc. How can I do this in ML?

Operators are just functions, once you prefix them with `op'. So you can treat them like any old function:
Standard ML of New Jersey v110.75 [built: Sat Nov 10 05:28:39 2012]
- op+;
val it = fn : int * int -> int
Meaning that you can pass them as arguments to higher-order functions as you would with any other function.
Note that if you want to get an infix binding for a name, you can do the converse:
- val op* = String.^;
val * = fn : string * string -> string
- "foo" * "bar";
val it = "foobar" : string
In other words, the only `unusual' thing about infix operators is that they can be magically turned into regular (prefix) names by prepending 'op'.

Related

Can you explain what happens with 2019 and what it is? [duplicate]

This question already has answers here:
How does the Comma Operator work
(9 answers)
Closed 2 years ago.
No compilation and runtime errors
Is 2019 is kind of variable or anything?
Explain this please
#include <stdio.h>
int main()
{
int a, b;
a= b = 2020, 2019;
printf("%d %d", a, b);
return 0;
}
a = b = 2020, 2019;
Is parsed as:
(a = (b = 2020)), 2019;
The , is a comma operator. First the left side of , is executed, it's result is discarded, a sequence point happens and then the right side is executed. So let's execute the left side:
First the inner braces need to be executed, ie. b = 2020 is executed, ie. b is assigned the value of 2020. The simple assignment operator = "returns" the same value that was stored, ie. in this case b = 2020 returns the value 2020. So now we have:
(a = 2020), 2019;
Then a = 2020 is executed - a is assigned the value of 2020. So now we have:
2020, 2019;
The result of the left side of comma operator is ignored (and side effects happen). So now we have:
2019;
It's just a value, something one could call an "empty statement" or "empty expression". A single value doesn't do anything, it is permitted by the language grammar and is like just ignored. Mostly empty statements with a (void) cast are used to remove compilers warnings about unused variables, they are used like int unused; (void)unused; - the (void)unused is just an expression that doesn't do anything.
Can you explain what happens with 2019
Nothing.
and what it is?
A rvalue of type int. A expression that has type int and value 2019.
Is 2019 is kind of variable or anything?
It's not a variable, it's just an expression. Try it out, any number is an expression, like int main() { 1; 2; 3; 1.0; 1 + 1; }

Explicitely initialize a function pointer [duplicate]

What is a lambda expression in C++11? When would I use one? What class of problem do they solve that wasn't possible prior to their introduction?
A few examples, and use cases would be useful.
The problem
C++ includes useful generic functions like std::for_each and std::transform, which can be very handy. Unfortunately they can also be quite cumbersome to use, particularly if the functor you would like to apply is unique to the particular function.
#include <algorithm>
#include <vector>
namespace {
struct f {
void operator()(int) {
// do something
}
};
}
void func(std::vector<int>& v) {
f f;
std::for_each(v.begin(), v.end(), f);
}
If you only use f once and in that specific place it seems overkill to be writing a whole class just to do something trivial and one off.
In C++03 you might be tempted to write something like the following, to keep the functor local:
void func2(std::vector<int>& v) {
struct {
void operator()(int) {
// do something
}
} f;
std::for_each(v.begin(), v.end(), f);
}
however this is not allowed, f cannot be passed to a template function in C++03.
The new solution
C++11 introduces lambdas allow you to write an inline, anonymous functor to replace the struct f. For small simple examples this can be cleaner to read (it keeps everything in one place) and potentially simpler to maintain, for example in the simplest form:
void func3(std::vector<int>& v) {
std::for_each(v.begin(), v.end(), [](int) { /* do something here*/ });
}
Lambda functions are just syntactic sugar for anonymous functors.
Return types
In simple cases the return type of the lambda is deduced for you, e.g.:
void func4(std::vector<double>& v) {
std::transform(v.begin(), v.end(), v.begin(),
[](double d) { return d < 0.00001 ? 0 : d; }
);
}
however when you start to write more complex lambdas you will quickly encounter cases where the return type cannot be deduced by the compiler, e.g.:
void func4(std::vector<double>& v) {
std::transform(v.begin(), v.end(), v.begin(),
[](double d) {
if (d < 0.0001) {
return 0;
} else {
return d;
}
});
}
To resolve this you are allowed to explicitly specify a return type for a lambda function, using -> T:
void func4(std::vector<double>& v) {
std::transform(v.begin(), v.end(), v.begin(),
[](double d) -> double {
if (d < 0.0001) {
return 0;
} else {
return d;
}
});
}
"Capturing" variables
So far we've not used anything other than what was passed to the lambda within it, but we can also use other variables, within the lambda. If you want to access other variables you can use the capture clause (the [] of the expression), which has so far been unused in these examples, e.g.:
void func5(std::vector<double>& v, const double& epsilon) {
std::transform(v.begin(), v.end(), v.begin(),
[epsilon](double d) -> double {
if (d < epsilon) {
return 0;
} else {
return d;
}
});
}
You can capture by both reference and value, which you can specify using & and = respectively:
[&epsilon, zeta] captures epsilon by reference and zeta by value
[&] captures all variables used in the lambda by reference
[=] captures all variables used in the lambda by value
[&, epsilon] captures all variables used in the lambda by reference but captures epsilon by value
[=, &epsilon] captures all variables used in the lambda by value but captures epsilon by reference
The generated operator() is const by default, with the implication that captures will be const when you access them by default. This has the effect that each call with the same input would produce the same result, however you can mark the lambda as mutable to request that the operator() that is produced is not const.
What is a lambda function?
The C++ concept of a lambda function originates in the lambda calculus and functional programming. A lambda is an unnamed function that is useful (in actual programming, not theory) for short snippets of code that are impossible to reuse and are not worth naming.
In C++ a lambda function is defined like this
[]() { } // barebone lambda
or in all its glory
[]() mutable -> T { } // T is the return type, still lacking throw()
[] is the capture list, () the argument list and {} the function body.
The capture list
The capture list defines what from the outside of the lambda should be available inside the function body and how.
It can be either:
a value: [x]
a reference [&x]
any variable currently in scope by reference [&]
same as 3, but by value [=]
You can mix any of the above in a comma separated list [x, &y].
The argument list
The argument list is the same as in any other C++ function.
The function body
The code that will be executed when the lambda is actually called.
Return type deduction
If a lambda has only one return statement, the return type can be omitted and has the implicit type of decltype(return_statement).
Mutable
If a lambda is marked mutable (e.g. []() mutable { }) it is allowed to mutate the values that have been captured by value.
Use cases
The library defined by the ISO standard benefits heavily from lambdas and raises the usability several bars as now users don't have to clutter their code with small functors in some accessible scope.
C++14
In C++14 lambdas have been extended by various proposals.
Initialized Lambda Captures
An element of the capture list can now be initialized with =. This allows renaming of variables and to capture by moving. An example taken from the standard:
int x = 4;
auto y = [&r = x, x = x+1]()->int {
r += 2;
return x+2;
}(); // Updates ::x to 6, and initializes y to 7.
and one taken from Wikipedia showing how to capture with std::move:
auto ptr = std::make_unique<int>(10); // See below for std::make_unique
auto lambda = [ptr = std::move(ptr)] {return *ptr;};
Generic Lambdas
Lambdas can now be generic (auto would be equivalent to T here if
T were a type template argument somewhere in the surrounding scope):
auto lambda = [](auto x, auto y) {return x + y;};
Improved Return Type Deduction
C++14 allows deduced return types for every function and does not restrict it to functions of the form return expression;. This is also extended to lambdas.
Lambda expressions are typically used to encapsulate algorithms so that they can be passed to another function. However, it is possible to execute a lambda immediately upon definition:
[&](){ ...your code... }(); // immediately executed lambda expression
is functionally equivalent to
{ ...your code... } // simple code block
This makes lambda expressions a powerful tool for refactoring complex functions. You start by wrapping a code section in a lambda function as shown above. The process of explicit parameterization can then be performed gradually with intermediate testing after each step. Once you have the code-block fully parameterized (as demonstrated by the removal of the &), you can move the code to an external location and make it a normal function.
Similarly, you can use lambda expressions to initialize variables based on the result of an algorithm...
int a = []( int b ){ int r=1; while (b>0) r*=b--; return r; }(5); // 5!
As a way of partitioning your program logic, you might even find it useful to pass a lambda expression as an argument to another lambda expression...
[&]( std::function<void()> algorithm ) // wrapper section
{
...your wrapper code...
algorithm();
...your wrapper code...
}
([&]() // algorithm section
{
...your algorithm code...
});
Lambda expressions also let you create named nested functions, which can be a convenient way of avoiding duplicate logic. Using named lambdas also tends to be a little easier on the eyes (compared to anonymous inline lambdas) when passing a non-trivial function as a parameter to another function. Note: don't forget the semicolon after the closing curly brace.
auto algorithm = [&]( double x, double m, double b ) -> double
{
return m*x+b;
};
int a=algorithm(1,2,3), b=algorithm(4,5,6);
If subsequent profiling reveals significant initialization overhead for the function object, you might choose to rewrite this as a normal function.
Answers
Q: What is a lambda expression in C++11?
A: Under the hood, it is the object of an autogenerated class with overloading operator() const. Such object is called closure and created by compiler.
This 'closure' concept is near with the bind concept from C++11.
But lambdas typically generate better code. And calls through closures allow full inlining.
Q: When would I use one?
A: To define "simple and small logic" and ask compiler perform generation from previous question. You give a compiler some expressions which you want to be inside operator(). All other stuff compiler will generate to you.
Q: What class of problem do they solve that wasn't possible prior to their introduction?
A: It is some kind of syntax sugar like operators overloading instead of functions for custom add, subrtact operations...But it save more lines of unneeded code to wrap 1-3 lines of real logic to some classes, and etc.! Some engineers think that if the number of lines is smaller then there is a less chance to make errors in it (I'm also think so)
Example of usage
auto x = [=](int arg1){printf("%i", arg1); };
void(*f)(int) = x;
f(1);
x(1);
Extras about lambdas, not covered by question. Ignore this section if you're not interest
1. Captured values. What you can to capture
1.1. You can reference to a variable with static storage duration in lambdas. They all are captured.
1.2. You can use lambda for capture values "by value". In such case captured vars will be copied to the function object (closure).
[captureVar1,captureVar2](int arg1){}
1.3. You can capture be reference. & -- in this context mean reference, not pointers.
[&captureVar1,&captureVar2](int arg1){}
1.4. It exists notation to capture all non-static vars by value, or by reference
[=](int arg1){} // capture all not-static vars by value
[&](int arg1){} // capture all not-static vars by reference
1.5. It exists notation to capture all non-static vars by value, or by reference and specify smth. more.
Examples:
Capture all not-static vars by value, but by reference capture Param2
[=,&Param2](int arg1){}
Capture all not-static vars by reference, but by value capture Param2
[&,Param2](int arg1){}
2. Return type deduction
2.1. Lambda return type can be deduced if lambda is one expression. Or you can explicitly specify it.
[=](int arg1)->trailing_return_type{return trailing_return_type();}
If lambda has more then one expression, then return type must be specified via trailing return type.
Also, similar syntax can be applied to auto functions and member-functions
3. Captured values. What you can not capture
3.1. You can capture only local vars, not member variable of the object.
4. Сonversions
4.1 !! Lambda is not a function pointer and it is not an anonymous function, but capture-less lambdas can be implicitly converted to a function pointer.
p.s.
More about lambda grammar information can be found in Working draft for Programming Language C++ #337, 2012-01-16, 5.1.2. Lambda Expressions, p.88
In C++14 the extra feature which has named as "init capture" have been added. It allow to perform arbitarily declaration of closure data members:
auto toFloat = [](int value) { return float(value);};
auto interpolate = [min = toFloat(0), max = toFloat(255)](int value)->float { return (value - min) / (max - min);};
A lambda function is an anonymous function that you create in-line. It can capture variables as some have explained, (e.g. http://www.stroustrup.com/C++11FAQ.html#lambda) but there are some limitations. For example, if there's a callback interface like this,
void apply(void (*f)(int)) {
f(10);
f(20);
f(30);
}
you can write a function on the spot to use it like the one passed to apply below:
int col=0;
void output() {
apply([](int data) {
cout << data << ((++col % 10) ? ' ' : '\n');
});
}
But you can't do this:
void output(int n) {
int col=0;
apply([&col,n](int data) {
cout << data << ((++col % 10) ? ' ' : '\n');
});
}
because of limitations in the C++11 standard. If you want to use captures, you have to rely on the library and
#include <functional>
(or some other STL library like algorithm to get it indirectly) and then work with std::function instead of passing normal functions as parameters like this:
#include <functional>
void apply(std::function<void(int)> f) {
f(10);
f(20);
f(30);
}
void output(int width) {
int col;
apply([width,&col](int data) {
cout << data << ((++col % width) ? ' ' : '\n');
});
}
One of the best explanation of lambda expression is given from author of C++ Bjarne Stroustrup in his book ***The C++ Programming Language*** chapter 11 (ISBN-13: 978-0321563842):
What is a lambda expression?
A lambda expression, sometimes also referred to as a lambda
function or (strictly speaking incorrectly, but colloquially) as a
lambda, is a simplified notation for defining and using an anonymous function object. Instead of defining a named class with an operator(), later making an object of that class, and finally
invoking it, we can use a shorthand.
When would I use one?
This is particularly useful when we want to pass an operation as an
argument to an algorithm. In the context of graphical user interfaces
(and elsewhere), such operations are often referred to as callbacks.
What class of problem do they solve that wasn't possible prior to their introduction?
Here i guess every action done with lambda expression can be solved without them, but with much more code and much bigger complexity. Lambda expression this is the way of optimization for your code and a way of making it more attractive. As sad by Stroustup :
effective ways of optimizing
Some examples
via lambda expression
void print_modulo(const vector<int>& v, ostream& os, int m) // output v[i] to os if v[i]%m==0
{
for_each(begin(v),end(v),
[&os,m](int x) {
if (x%m==0) os << x << '\n';
});
}
or via function
class Modulo_print {
ostream& os; // members to hold the capture list int m;
public:
Modulo_print(ostream& s, int mm) :os(s), m(mm) {}
void operator()(int x) const
{
if (x%m==0) os << x << '\n';
}
};
or even
void print_modulo(const vector<int>& v, ostream& os, int m)
// output v[i] to os if v[i]%m==0
{
class Modulo_print {
ostream& os; // members to hold the capture list
int m;
public:
Modulo_print (ostream& s, int mm) :os(s), m(mm) {}
void operator()(int x) const
{
if (x%m==0) os << x << '\n';
}
};
for_each(begin(v),end(v),Modulo_print{os,m});
}
if u need u can name lambda expression like below:
void print_modulo(const vector<int>& v, ostream& os, int m)
// output v[i] to os if v[i]%m==0
{
auto Modulo_print = [&os,m] (int x) { if (x%m==0) os << x << '\n'; };
for_each(begin(v),end(v),Modulo_print);
}
Or assume another simple sample
void TestFunctions::simpleLambda() {
bool sensitive = true;
std::vector<int> v = std::vector<int>({1,33,3,4,5,6,7});
sort(v.begin(),v.end(),
[sensitive](int x, int y) {
printf("\n%i\n", x < y);
return sensitive ? x < y : abs(x) < abs(y);
});
printf("sorted");
for_each(v.begin(), v.end(),
[](int x) {
printf("x - %i;", x);
}
);
}
will generate next
0
1
0
1
0
1
0
1
0
1
0 sortedx - 1;x - 3;x - 4;x - 5;x - 6;x - 7;x - 33;
[] - this is capture list or lambda introducer: if lambdas require no access to their local environment we can use it.
Quote from book:
The first character of a lambda expression is always [. A lambda
introducer can take various forms:
• []: an empty capture list. This
implies that no local names from the surrounding context can be used
in the lambda body. For such lambda expressions, data is obtained from
arguments or from nonlocal variables.
• [&]: implicitly capture by
reference. All local names can be used. All local variables are
accessed by reference.
• [=]: implicitly capture by value. All local
names can be used. All names refer to copies of the local variables
taken at the point of call of the lambda expression.
• [capture-list]: explicit capture; the capture-list is the list of names of local variables to be captured (i.e., stored in the object) by reference or by value. Variables with names preceded by & are captured by
reference. Other variables are captured by value. A capture list can
also contain this and names followed by ... as elements.
• [&, capture-list]: implicitly capture by reference all local variables with names not men- tioned in the list. The capture list can contain this. Listed names cannot be preceded by &. Variables named in the
capture list are captured by value.
• [=, capture-list]: implicitly capture by value all local variables with names not mentioned in the list. The capture list cannot contain this. The listed names must be preceded by &. Vari- ables named in the capture list are captured by reference.
Note that a local name preceded by & is always captured by
reference and a local name not pre- ceded by & is always captured by
value. Only capture by reference allows modification of variables in
the calling environment.
Additional
Lambda expression format
Additional references:
Wiki
open-std.org, chapter 5.1.2
The lambda's in c++ are treated as "on the go available function".
yes its literally on the go, you define it; use it; and as the parent function scope finishes the lambda function is gone.
c++ introduced it in c++ 11 and everyone started using it like at every possible place.
the example and what is lambda can be find here https://en.cppreference.com/w/cpp/language/lambda
i will describe which is not there but essential to know for every c++ programmer
Lambda is not meant to use everywhere and every function cannot be replaced with lambda. It's also not the fastest one compare to normal function. because it has some overhead which need to be handled by lambda.
it will surely help in reducing number of lines in some cases.
it can be basically used for the section of code, which is getting called in same function one or more time and that piece of code is not needed anywhere else so that you can create standalone function for it.
Below is the basic example of lambda and what happens in background.
User code:
int main()
{
// Lambda & auto
int member=10;
auto endGame = [=](int a, int b){ return a+b+member;};
endGame(4,5);
return 0;
}
How compile expands it:
int main()
{
int member = 10;
class __lambda_6_18
{
int member;
public:
inline /*constexpr */ int operator()(int a, int b) const
{
return a + b + member;
}
public: __lambda_6_18(int _member)
: member{_member}
{}
};
__lambda_6_18 endGame = __lambda_6_18{member};
endGame.operator()(4, 5);
return 0;
}
so as you can see, what kind of overhead it adds when you use it.
so its not good idea to use them everywhere.
it can be used at places where they are applicable.
Well, one practical use I've found out is reducing boiler plate code. For example:
void process_z_vec(vector<int>& vec)
{
auto print_2d = [](const vector<int>& board, int bsize)
{
for(int i = 0; i<bsize; i++)
{
for(int j=0; j<bsize; j++)
{
cout << board[bsize*i+j] << " ";
}
cout << "\n";
}
};
// Do sth with the vec.
print_2d(vec,x_size);
// Do sth else with the vec.
print_2d(vec,y_size);
//...
}
Without lambda, you may need to do something for different bsize cases. Of course you could create a function but what if you want to limit the usage within the scope of the soul user function? the nature of lambda fulfills this requirement and I use it for that case.
C++ 11 introduced lambda expression to allow us write an inline function which can be used for short snippets of code
[ capture clause ] (parameters) -> return-type
{
definition of method
}
Generally return-type in lambda expression are evaluated by compiler itself and we don’t need to specify that explicitly and -> return-type part can be ignored but in some complex case as in conditional statement, compiler can’t make out the return type and we need to specify that.
// C++ program to demonstrate lambda expression in C++
#include <bits/stdc++.h>
using namespace std;
// Function to print vector
void printVector(vector<int> v)
{
// lambda expression to print vector
for_each(v.begin(), v.end(), [](int i)
{
std::cout << i << " ";
});
cout << endl;
}
int main()
{
vector<int> v {4, 1, 3, 5, 2, 3, 1, 7};
printVector(v);
// below snippet find first number greater than 4
// find_if searches for an element for which
// function(third argument) returns true
vector<int>:: iterator p = find_if(v.begin(), v.end(), [](int i)
{
return i > 4;
});
cout << "First number greater than 4 is : " << *p << endl;
// function to sort vector, lambda expression is for sorting in
// non-decreasing order Compiler can make out return type as
// bool, but shown here just for explanation
sort(v.begin(), v.end(), [](const int& a, const int& b) -> bool
{
return a > b;
});
printVector(v);
// function to count numbers greater than or equal to 5
int count_5 = count_if(v.begin(), v.end(), [](int a)
{
return (a >= 5);
});
cout << "The number of elements greater than or equal to 5 is : "
<< count_5 << endl;
// function for removing duplicate element (after sorting all
// duplicate comes together)
p = unique(v.begin(), v.end(), [](int a, int b)
{
return a == b;
});
// resizing vector to make size equal to total different number
v.resize(distance(v.begin(), p));
printVector(v);
// accumulate function accumulate the container on the basis of
// function provided as third argument
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int f = accumulate(arr, arr + 10, 1, [](int i, int j)
{
return i * j;
});
cout << "Factorial of 10 is : " << f << endl;
// We can also access function by storing this into variable
auto square = [](int i)
{
return i * i;
};
cout << "Square of 5 is : " << square(5) << endl;
}
Output
4 1 3 5 2 3 1 7
First number greater than 4 is : 5
7 5 4 3 3 2 1 1
The number of elements greater than or equal to 5 is : 2
7 5 4 3 2 1
Factorial of 10 is : 3628800
Square of 5 is : 25
A lambda expression can have more power than an ordinary function by having access to variables from the enclosing scope. We can capture external variables from enclosing scope by three ways :
Capture by reference
Capture by value
Capture by both (mixed capture)
The syntax used for capturing variables :
[&] : capture all external variable by reference
[=] : capture all external variable by value
[a, &b] : capture a by value and b by reference
A lambda with empty capture clause [ ] can access only those variable which are local to it.
#include <bits/stdc++.h>
using namespace std;
int main()
{
vector<int> v1 = {3, 1, 7, 9};
vector<int> v2 = {10, 2, 7, 16, 9};
// access v1 and v2 by reference
auto pushinto = [&] (int m)
{
v1.push_back(m);
v2.push_back(m);
};
// it pushes 20 in both v1 and v2
pushinto(20);
// access v1 by copy
[v1]()
{
for (auto p = v1.begin(); p != v1.end(); p++)
{
cout << *p << " ";
}
};
int N = 5;
// below snippet find first number greater than N
// [N] denotes, can access only N by value
vector<int>:: iterator p = find_if(v1.begin(), v1.end(), [N](int i)
{
return i > N;
});
cout << "First number greater than 5 is : " << *p << endl;
// function to count numbers greater than or equal to N
// [=] denotes, can access all variable
int count_N = count_if(v1.begin(), v1.end(), [=](int a)
{
return (a >= N);
});
cout << "The number of elements greater than or equal to 5 is : "
<< count_N << endl;
}
Output:
First number greater than 5 is : 7
The number of elements greater than or equal to 5 is : 3
One problem it solves: Code simpler than lambda for a call in constructor that uses an output parameter function for initializing a const member
You can initialize a const member of your class, with a call to a function that sets its value by giving back its output as an output parameter.

Precedence of arr[x++]--

I am confused on how to parse precedence of operations in C. the line
countArray[*string++]--
Is executing how I want it to, but I don't understand the steps that result in countArray[*string]-- being evaluated before *string++.
My research on C precedence and binding didn't provide answers that relate to this case, and I'm wondering about general rules for post/pre-increment and post/pre-decrement when in combination with other post/pre - crements.
How does C know to evaluate it this way?
void discountChars(char* string, char** countArray)
{
int test;
while(*string) {
test = *string;
//why is countArray[*string]-- evaluated before string++ is incremented?
countArray[*string++]--;
printf("countArray[%d] = %d\n", test, countArray[test]);
}
}
You can break this:
countArray[*string++]--;
down into this:
char index = *string; // get char from `string` into temporary index
string++; // increment `string`
countArray[index]--; // decrement `countArray` value at given index
and then it should be clearer what's going on.
As it has been stated many times, precedence has no connection to the order of evaluation. The only thing in C language that can affect order of evaluation is sequencing. Precedence has nothing to do with it.
It is also unclear where you got the strange idea that "countArray[*string]-- is being evaluated before *string++". This is simply impossible. The expression in [] will always be evaluated first, since its result is required to perform the element access (i.e. sequenced before the element access). Which means that the opposite is true: *string++ is evaluated before countArray[*string]--.
So, the sequence of steps here is
Evaluate *string++. The result of this expression is the original value of *string. Let's designate it tmp.
This expression also "schedules" a side-effect - increment of string. But this increment does not have to happen right now.
Evaluate countArray[tmp]--. The result of this expression is the original value of countArray[tmp]. This result is immediately discareded.
This expression also "schedules" a side-effect - decrement of countArray[tmp]. But this decrement does not have to happen right now.
Complete the evaluation of the full expression . If any of the above side-effects are still pending, complete them right now.
For example, one possible evaluation schedule might look as follows
char tmp = *string; // subexpression inside `[]`
countArray[tmp]; // full expression, result discarded
countArray[tmp] = countArray[tmp] - 1; // side-effect
string = string + 1; // side-effect
Another possible evaluation schedule is
char tmp = *string; // subexpression inside `[]`
string = string + 1; // side-effect
countArray[tmp]; // full expression, result discarded
countArray[tmp] = countArray[tmp] - 1; // side-effect
It can even be evaluated as
string = string + 1; // side-effect
char tmp = *(string - 1); // subexpression inside `[]`
countArray[tmp]; // full expression, result discarded
countArray[tmp] = countArray[tmp] - 1; // side-effect
Precedence controls groupings of operators and operands, not order of evaluation.
The expression *string++ must be evaluated before it can be used as an array subscript; however, the side effect of updating string may happen after the larger expression has been evaluated. The following sequence of events is allowed:
t1 <- *string
countArray[t1] <- countArray[t1] - 1
string <- string + 1
Then again, so is the following:
t1 <- *string
string <- string + 1
countArray[t1] <- countArray[t1] - 1

Invalid output in `int` array

I am trying to learn pointers and I just encountered a situation I do not understand.
int main()
{
int num[3][2]={3,6,9,12,15,18};
printf("%d %d",*(num+1)[1],**(num+2));
}
As per what I have learnt the output should be :
12 15
but actually it is:
15 15
Why? Please clarify as to how things are calculated here as what I think is first *(num+1) get calculated and point to the 1st one i.e. {9,12} and then [1] should dereference to first element i.e 12.
I am using GCC compiler.
In your data,
int num[3][2]={3,6,9,12,15,18};
equivalent to:
int num[3][2]={{3,6},{9,12},{15,18}};
i.e.
num[0][0] = 3
num[0][1] = 6
num[1][0] = 9
num[1][1] = 12
num[2][0] = 15
num[2][1] = 18
thus,
*(num+1)[1]
= *(*(num+1+1))
= num[2][0]
=15
and,
**(num+2))
= num[2][0]
=15
Array subscript [] operator has higher precedence than dereference operator *.
This means the expression *(num+1)[1] is equivalent to *((num+1)[1])
And if we take it apart
*(*((num+1)+1))
*(*(num+2))
*(num[2])
num[2][0]
See C Operator Precedence, [] is processed before *
That means
(num+1)[1]
*((num+1)+1)
*(num+2)
Together with the additional * (not written in my example),
it becomes the same as the second thing.

Lvalue required error with macro

Why does the following code report an Lvalue required error?? And how can we write a macro that receives an array and the number of elements in the array as arguments and then print out the elements of the array??
#define arr(b) printf("%d",b++);\
printf("%d",b);
int main()
{
arr(5);
}
If you expand the macro, you get the following:
int main()
{
printf("%d",5++);
printf("%d",5);
}
You cannot postincrement the constant 5, so you get an error.
Remember, macros aren't functions. If you want it to act like a function, simply make a function:
void arr(int b) {
printf("%d",b++);
printf("%d",b);
}
Because part of that macro expands to 5++, which is not valid C. Consider using b+1 instead of b++.
The first l in lvalue stands for left.
Only left values can be assigned.
when you write x ++ you mean x = x + 1 (also you get a value from it).
So the problem is it does not make sense to write 5 = 5 + 1
maybe you would like to do this:
int x = 5;
arr(x);

Resources