How do you easily differentiate the use of * as a pointer, * as a de-reference operator, * as a multiplication operator in C? - malloc

The use of * is all so confusing especially for us new comers to C. I mean, how do you easily differentiate the use of * as a pointer, * as a de-reference operator, * as a multiplication operator? I see alot of different use of * online and it's quite confusing, especially regarding different positions of the * e.g. as in the sample code below. What positions of * are correct and advisable to use to avoid confusion with pointers, de-referencing and multiplication?
Code is just sample and may...infact will not compile.
int main(void){
int *size, length, width;
*size1= malloc(sizeof(int) * length);
*size2= (int *) malloc(width * sizeof(int) * width);
*size3= malloc(sizeof(int) *length);
printf("%d\n%d\n%d\n", size1,size2,size3);
return (0);
}
N.B: I'm new in C and pls don't refer me to useless links and ("supposedly") duplicates that doesn't answer exactly same question as this...pls allow others to air their views so we get maximum answers, none knows it all, u will be surprised that something new can pop-up, even for the so called C old-timers.

When you read C code, you must be able to distinguish definitions and expressions. A definition starts with a type optionally preceded by a storage class such as extern, static, typedef... and/or type qualifiers such as const and, volatile. A star in front of the identifier being defined indicates that this variable is a pointer, multiple stars indicate multiple levels of indirection.
In an expression, a star can occur as a binary operator, between operands, or as unary operator, in front of its operand. The binary operator * is the multiplication operator, whereas the unary * is the dereference operator.
As a rule of thumb, a * that follows an identifier or a postfix operator is a multiplication operator. Postfix operators are ++, --, indexing with [] and calling a function with optional arguments inside ().
The confusion comes from the conciseness of the C language, which allows the programmer to combine these different uses at will:
int x=0,*p=&x,n=*p**p;
This ugly line is indeed confusing. Let's first insert meaningful spaces to improve readability:
int x = 0, *p = &x, n = *p * *p;
Spacing is mostly unnecessary for the C compiler, but following simple rules increases readability for humans:
add a space on both sides of binary operators
add a space after , and ; except at the end of a line
do not insert a space between unary operators and their operand, except for sizeof.
indent code in a consistent manner, typically 4 spaces per level
The above line of code defines 3 variables x, p and n.
* p is a pointer to int, while x and n are int variables.
* x is initialized to 0
* p is initialized to the address of x.
* the initializer for n is the result of multiplying of the value pointed to by p by itself.
Defining multiple variables with different levels of indirection in the same definition is frowned upon because it is confusing and error prone. Rewriting the above definition on 3 lines is highly advisable:
int x = 0;
int *p = &x;
int n = *p * *p;

Related

Modeling RLC in OpenModelica. Error - Type mismatch,between Complex and Real

EDITED 28-04-2021
I trying to build a RLC-chain in OpenModelica.
When I entering the several functions in "equation", appears an error (see comments)
I declared some of the variables above, but the errors did not disappear
There are RLC-chain
There are formulas
model Lab5
extends Modelica.Icons.Example;
type Voltage=Real(unit="V");
type Current=Real(unit="A");
type Resistance=Real(unit="Ohm");
type Capacitance=Real(unit="F");
type Inductance =Real(unit="H");
parameter Modelica.SIunits.Resistance R=100 "Resistance";
parameter Modelica.SIunits.Inductance L=1 "Inductance";
parameter Modelica.SIunits.Voltage Vb=24 "Total DC Voltage";
parameter Modelica.SIunits.Capacitance C=1e-3 "Capacitance";
Voltage V;
Current i_L;
Current i_R;
Current i_C;
Current icomp;
equation
Z1_f=Modelica.ComplexMath.'sqrt'(Complex(re=-1)*(2*Modelica.Constants.pi*f*L*(1/(2*Modelica.Constants.pi*f*C)));
** //Error:
Type mismatch in equation Z1_f=Modelica.ComplexMath.'sqrt'(Complex.'*'.multiply(Complex(-1.0, 0.0),
Complex.'constructor'.fromReal(L / C, 0.0))) of type Real=record Complex
Real re;
Real im;
end Complex;.**
Z2_f=R;
KPF=Z2_f/(Z1_f+Z2_f);
APF=ModelicaReference.Operators.'abs(KPF)';
FPF=Modelica.ComplexMath.arg(KPF);
V = i_R * R;
C * der(V) = i_C;
L * der(i_L) = Vb - V;
i_L = i_R + i_C;
annotation(
uses(Modelica(version = "3.2.3")));
end Lab5;
I tried to change the syntax and made this code:
Z1_f=Modelica.ComplexMath.'sqrt'(Complex*Complex(re=2*Modelica.Constants.pi*f*L*(1/(2*Modelica.Constants.pi*f*C))));
But now this error:
Operator overloading requires exactly one matching expression, but found 0 expressions:
But if I assign a complex to one complex in a parenthesis to another complex, thereby assigning 1 argument (not 0, as in the previous error), then the error again refers to the incorrectly composed constructor and the conversion from complex to real.
Z1_f=Modelica.ComplexMath.'sqrt'(Complex(Complex(re=(2*Modelica.Constants.pi*f*L*(1/(2*Modelica.Constants.pi*f*C))))));
The are 2 big errors:
Type mismatch for positional argument 1 in Complex(re=Complex.'constructor'.fromReal(L / C, 0.0)). The argument has type:
record Complex
Real re;
Real im;
end Complex;
expected type:
Real
Complex.'constructor'.fromReal(re=Complex.'constructor'.fromReal(L / C, 0.0)). The argument has type:
record Complex
Real re;
Real im;
end Complex;
expected type:
Real
How I can to solve this problem between the complex and real variablesO?
Because in Modelica a lot of equations between complex and real datas.
This seems like homework, so I will give you some hints.
Instead of defining pi, use Modelica.Constants.pi.
ModelicaReference is just a library for documentation you cannot use any of the (quoted) operators from there, remove ModelicaReference.Operators. and the quotes
You need to declare all the variables that appear in the equation section, with correct type (Real or Complex), you are now missing a lot of them
ModelicaReference.Operators.'abs(KPF)' -> abs(KPF)
as far as I see you are using complex numbers, for that you need to use type Complex
For operators on Complex you use: Complex operators and Modelica.ComplexMath, i.e. Modelica.ComplexMath.'sqrt'(Complex(re=-1, im=0))

Rcpp: continued fractions and precision [duplicate]

How come that in the following snippet
int a = 7;
int b = 3;
double c = 0;
c = a / b;
c ends up having the value 2, rather than 2.3333, as one would expect. If a and b are doubles, the answer does turn to 2.333. But surely because c already is a double it should have worked with integers?
So how come int/int=double doesn't work?
This is because you are using the integer division version of operator/, which takes 2 ints and returns an int. In order to use the double version, which returns a double, at least one of the ints must be explicitly casted to a double.
c = a/(double)b;
Here it is:
a) Dividing two ints performs integer division always. So the result of a/b in your case can only be an int.
If you want to keep a and b as ints, yet divide them fully, you must cast at least one of them to double: (double)a/b or a/(double)b or (double)a/(double)b.
b) c is a double, so it can accept an int value on assignement: the int is automatically converted to double and assigned to c.
c) Remember that on assignement, the expression to the right of = is computed first (according to rule (a) above, and without regard of the variable to the left of =) and then assigned to the variable to the left of = (according to (b) above). I believe this completes the picture.
With very few exceptions (I can only think of one), C++ determines the
entire meaning of an expression (or sub-expression) from the expression
itself. What you do with the results of the expression doesn't matter.
In your case, in the expression a / b, there's not a double in
sight; everything is int. So the compiler uses integer division.
Only once it has the result does it consider what to do with it, and
convert it to double.
When you divide two integers, the result will be an integer, irrespective of the fact that you store it in a double.
c is a double variable, but the value being assigned to it is an int value because it results from the division of two ints, which gives you "integer division" (dropping the remainder). So what happens in the line c=a/b is
a/b is evaluated, creating a temporary of type int
the value of the temporary is assigned to c after conversion to type double.
The value of a/b is determined without reference to its context (assignment to double).
In C++ language the result of the subexpresison is never affected by the surrounding context (with some rare exceptions). This is one of the principles that the language carefully follows. The expression c = a / b contains of an independent subexpression a / b, which is interpreted independently from anything outside that subexpression. The language does not care that you later will assign the result to a double. a / b is an integer division. Anything else does not matter. You will see this principle followed in many corners of the language specification. That's juts how C++ (and C) works.
One example of an exception I mentioned above is the function pointer assignment/initialization in situations with function overloading
void foo(int);
void foo(double);
void (*p)(double) = &foo; // automatically selects `foo(fouble)`
This is one context where the left-hand side of an assignment/initialization affects the behavior of the right-hand side. (Also, reference-to-array initialization prevents array type decay, which is another example of similar behavior.) In all other cases the right-hand side completely ignores the left-hand side.
The / operator can be used for integer division or floating point division. You're giving it two integer operands, so it's doing integer division and then the result is being stored in a double.
This is technically a language-dependent, but almost all languages treat this subject the same. When there is a type mismatch between two data types in an expression, most languages will try to cast the data on one side of the = to match the data on the other side according to a set of predefined rules.
When dividing two numbers of the same type (integers, doubles, etc.) the result will always be of the same type (so 'int/int' will always result in int).
In this case you have
double var = integer result
which casts the integer result to a double after the calculation in which case the fractional data is already lost. (most languages will do this casting to prevent type inaccuracies without raising an exception or error).
If you'd like to keep the result as a double you're going to want to create a situation where you have
double var = double result
The easiest way to do that is to force the expression on the right side of an equation to cast to double:
c = a/(double)b
Division between an integer and a double will result in casting the integer to the double (note that when doing maths, the compiler will often "upcast" to the most specific data type this is to prevent data loss).
After the upcast, a will wind up as a double and now you have division between two doubles. This will create the desired division and assignment.
AGAIN, please note that this is language specific (and can even be compiler specific), however almost all languages (certainly all the ones I can think of off the top of my head) treat this example identically.
For the same reasons above, you'll have to convert one of 'a' or 'b' to a double type. Another way of doing it is to use:
double c = (a+0.0)/b;
The numerator is (implicitly) converted to a double because we have added a double to it, namely 0.0.
The important thing is one of the elements of calculation be a float-double type. Then to get a double result you need to cast this element like shown below:
c = static_cast<double>(a) / b;
or
c = a / static_cast(b);
Or you can create it directly::
c = 7.0 / 3;
Note that one of elements of calculation must have the '.0' to indicate a division of a float-double type by an integer. Otherwise, despite the c variable be a double, the result will be zero too (an integer).

Bison simple postfix calculator using union with struct

Im making a simple calculator that prints postfix to learn bison. i could make the postfix part work ,but now i need to do assigments to variables (a-z) tex: a=3+2; should print: a32+=; for example. Im trying modified my working postfix code to be able to read a char too.
If I understand correctly, to be able to put different types in the $$ i need a union and to make the nodes i should use a struct because in my case 'expr' can be a int or a char.
This is my parser:
%code requires{
struct nPtr{
char *val;
int num;
};
}
%union {
int iValue;
char sIndex;
struct nPtr *e;
};
%token PLUS MINUS STAR LPAREN RPAREN NEWLINE DIV ID NUMBER POW EQL
%type <iValue> NUMBER
%type <sIndex> ID
%type <e> expr line
%left PLUS MINUS
%left STAR DIV
%left POW
%left EQL
%%
line : /* empty */
|line expr NEWLINE { printf("=\n%d\n", $2.num); }
expr : LPAREN expr RPAREN { $$.num = $2.num; }
| expr PLUS expr { $$.num = $1.num + $3.num; printf("+"); }
| expr MINUS expr { $$.num = $1.num - $3.num; printf("-"); }
| expr STAR expr { $$.num = $1.num * $3.num; printf("*"); }
| expr DIV expr { $$.num = $1.num / $3.num; printf("/");}
| expr POW expr { $$.num = pow($1.num, $3.num); printf("**");}
| NUMBER { $$.num = $1.num; printf("%d", yylval); }
| ID EQL expr { printf("%c", yylval); }
;
%%
I have this in the lex to handle the "=" and variables
"=" { return EQL; }
[a-z] { yylval.sIndex = strdup(yytext); return ID; }
i get and error
warning empty rule for typed nonterminal and no action
the only answer i found here about that is this:
Bison warning: Empty rule for typed nonterminal
It says to just remove the /* empty */ part in:
line: /* empty */
| line expr NEWLINE { printf("=\n%d\n", $2.num); }
when i do that i get 3 new warnings:
warning 3 nonterminal useless in grammar
warning 10 rules useless in grammar
fatal error: start symbol line does not derive any sentence
I googled and got some solutions that just gave me other problems, for example.
when i change:
line:line expr NEWLINE { printf("=\n%d\n", $2.num); }
to
line:expr NEWLINE { printf("=\n%d\n", $2.num); }
bison works but when i try to run the code in visual studio i get a lot of errors like:
left of '.e' must have struct/union type
'pow': too few arguments for call
'=': cannot convert from 'int' to 'YYSTYPE'
thats as afar as i got. I cant find a simple example similar to my needs. I just want to make 'expr' be able to read a char and print it. If someone could check my code and recommend some changes . it will be really really appreciated.
It is important to actually understand what you are asking Bison to do, and what it is telling you when it suggests that your instructions are wrong.
Applying a fix from someone else's problem will only work if they made the same mistake as you did. Just making random changes based on Google searching is neither a very structured way to debug nor to learn a new tool.
Now, what you said was:
%type <e> expr line
Which means that expr and line both produce a value whose union tag is e. (Tag e is a pointer to a struct nPtr. I doubt that's what you wanted either, but we'll start with the Bison warnings.)
If a non-terminal produces a value, it produce a value in every production. To produce a value, the semantic rule needs to assign a value (of the correct tag-type) to $$. For convenience, if there is no semantic action and if $1 has the correct tag-type, then Bison will provide the default rule $$ = $1. (That sentence is not quite correct but it's a useful approximation.) Many people think that you should not actually rely on this default, but I think it's OK as long as you know that it is happening, and have verified that the preconditions are valid.
In your case, you have two productions for line. Neither of them assigns a value to $$. This might suggest that you didn't really intend for line to even have a semantic value, and if we look more closely, we'll see that you never attempt to use a semantic value for any instance of the non-terminal line. Bison does not, as far as I know, attempt such a detailed code examination, but it is capable of noting that the production:
line : /* empty */
has no semantic action, and
does not have any symbols on the right-hand side, so no default action can be constructed.
Consequently, it warns you that there is some circumstance in which line will not have its value set. Think of this as the same warning as your C compiler might give you if it notices that a variable you use has never had a value assigned to it.
In this case, as I said, Bison has not noticed that you never use value of line. It just assumes that you wouldn't have declared the type of the value if you don't intend to somehow provide a value. You did declare the type, and you never provide a value. So your instructions to Bison were not clear, right?
Now, the solution is not to remove the production. There is no problem with the production, and if you remove it then line is left with only one production:
line : line expr NEWLINE
That's a recursive production, and the recursion can only terminate if there is some other production for line which does not recurse. That would be the production line: %empty, which you just deleted. So now Bison can see that the non-terminal line is useless. It is useless because it can never derive any string without non-terminals.
But that's a big problem, because that's the non-terminal your grammar is supposed to recognize. If line can't derive any string, then your grammar cannot recognize anything. Also, because line is useless, and expr is only used by a production in line (other than recursive uses), expr itself can never actually be used. So it, too, becomes useless. (You can think of this as the equivalent of your C compiler complaining that you have unreachable code.)
So then you attempt to fix the problem by making (the only remaining) rule for line non-recursive. Now you have:
line : expr NEWLINE
That's fine, and it makes line useful again. But it does not recognise the language you originally set out to recognise, because it will now only recognise a single line. (That is, an expr followed by a NEWLINE, as the production says.)
I hope you have now figured out that your original problem was not the grammar, which was always correct, but rather the fact that you told Bison that line produced a value, but you did not actually do anything to provide that value. In other words, the solution would have been to not tell Bison that line produces a value. (You could, instead, provide a value for line in the semantic rule associated with every production for line, but why would you do that if you have no intention of every using that value?)
Now, let's go back to the actual type declarations, to see why the C compiler complains. We can start with a simple one:
expr : NUM { $$.num = $1.num; }
$$ refers the the expr itself, which is declared as having type tag e, which is a struct nPtr *. The star is important: it indicates that the semantic value is a pointer. In order to get at a field in a struct from a pointer to the struct, you need to use the -> operator, just like this simple C example:
struct nPtr the_value; /* The actual struct */
struct nPtr *p = &the_value; /* A pointer to the struct */
p.num = 3; /* Error: p is not a struct */
p->num = 3; /* Fine. p points to a struct */
/* which has a field called num */
(*p).num = 3; /* Also fine, means exactly the same thing. */
/* But don't write this. p->num is much */
/* more readable. */
It's also worth noting that in the C example, we had to make sure that p was initialised to the address of some actual memory. If we hadn't done that and we attempted to assign something to p->num, then we would be trying to poke a value into an undefined address. If you're lucky, that would segfault. Otherwise, it might overwrite anything in your executable.
If any of that was not obvious, please go back to your C textbook and make sure that you understand how C pointers work, before you try to use them.
So, that was the $$.num part. The actual statement was
$$.num = $1.num;
So now lets look at the right-hand side. $1 refers to a NUM which has tag type iValue, which is an int. An int is not a struct and it has no named fields. $$.num = $1.num is going to be processed into something like:
int i = <some value>;
$$.num = i.num;
which is totally meaningless. Here, the compiler will again complain that iValue is not a struct, but for a different reason: on the left-hand side, e was a pointer to a struct (which is not a struct); on the right-hand side iValue is an integer (which is also not a struct).
I hope that gives you some ideas on what you need to do. If in doubt, there are a variety of fully-worked examples in the Bison manual.

On use of parenthesis

So I was looking over some A-Levels Computer Science past papers, and stumbled into this:
Now, my first reaction was that there is no need for parenthesis on line 6. Reason being that algebraic operators take precedence over comparisons which take precedence over boolean ones.
As a small example from Java:
int a = 100;
int b = 100;
int c = 100;
int d = 100;
if( ((c+d) > 180) && ((a+b+c+d)) >= 320)
System.out.println("greater");
if(c+d > 180 && a+b+c+d >=320)
System.out.println("greateragain");
Both if statements are evaluated to true.
So, am I right in thinking parenthesis are only for human readability in this case or...?
You can say: "The use of parentheses makes the precendence of evaluation explicit, disregarding of the operator precendence of the language in use."
The comments above describe well that operator precendence is language specific. For example, in Pascal, logical operators such as AND seem to have higher precendence than math operators, and interpreted as binary AND. In contrast in C, the && has lower precedence, hence you can save some parentheses.
Therefore, it sounds like a wise idea to always use parentheses in case of a possible ambiguity, or at least until you're mastering the language in use.
BASIC was one of the early languages that took advantage of the fact that logical operators and bit-wise operators can share the same mnemonic.
In the example - c+d > 180 AND a+b+c+d >= 320 could (by a stretch of the imagination) have been interpreted as (c + d) > (180 AND a) + b + c + (d > 320). For this reason it is necessary to add brackets to eremove all ambiguity.

What is call-by-need?

I want to know what is call-by-need.
Though I searched in wikipedia and found it here: http://en.wikipedia.org/wiki/Evaluation_strategy,
but could not understand properly.
If anyone can explain with an example and point out the difference with call-by-value, it would be a great help.
Suppose we have the function
square(x) = x * x
and we want to evaluate square(1+2).
In call-by-value, we do
square(1+2)
square(3)
3*3
9
In call-by-name, we do
square(1+2)
(1+2)*(1+2)
3*(1+2)
3*3
9
Notice that since we use the argument twice, we evaluate it twice. That would be wasteful if the argument evaluation took a long time. That's the issue that call-by-need fixes.
In call-by-need, we do something like the following:
square(1+2)
let x = 1+2 in x*x
let x = 3 in x*x
3*3
9
In step 2, instead of copying the argument (like in call-by-name), we give it a name. Then in step 3, when we notice that we need the value of x, we evaluate the expression for x. Only then do we substitute.
BTW, if the argument expression produced something more complicated, like a closure, there might be more shuffling of lets around to eliminate the possibility of copying. The formal rules are somewhat complicated to write down.
Notice that we "need" values for the arguments to primitive operations like + and *, but for other functions we take the "name, wait, and see" approach. We would say that the primitive arithmetic operations are "strict". It depends on the language, but usually most primitive operations are strict.
Notice also that "evaluation" still means to reduce to a value. A function call always returns a value, not an expression. (One of the other answers got this wrong.) OTOH, lazy languages usually have lazy data constructors, which can have components that are evaluated on-need, ie, when extracted. That's how you can have an "infinite" list---the value you return is a lazy data structure. But call-by-need vs call-by-value is a separate issue from lazy vs strict data structures. Scheme has lazy data constructors (streams), although since Scheme is call-by-value, the constructors are syntactic forms, not ordinary functions. And Haskell is call-by-name, but it has ways of defining strict data types.
If it helps to think about implementations, then one implementation of call-by-name is to wrap every argument in a thunk; when the argument is needed, you call the thunk and use the value. One implementation of call-by-need is similar, but the thunk is memoizing; it only runs the computation once, then it saves it and just returns the saved answer after that.
Imagine a function:
fun add(a, b) {
return a + b
}
And then we call it:
add(3 * 2, 4 / 2)
In a call-by-name language this will be evaluated so:
a = 3 * 2 = 6
b = 4 / 2 = 2
return a + b = 6 + 2 = 8
The function will return the value 8.
In a call-by-need (also called a lazy language) this is evaluated like so:
a = 3 * 2
b = 4 / 2
return a + b = 3 * 2 + 4 / 2
The function will return the expression 3 * 2 + 4 / 2. So far almost no computational resources have been spent. The whole expression will be computed only if its value is needed - say we wanted to print the result.
Why is this useful? Two reasons. First if you accidentally include dead code it doesn't weigh your program down and thus can be a lot more efficient. Second it allows to do very cool things like efficiently calculating with infinite lists:
fun takeFirstThree(list) {
return [list[0], list[1], list[2]]
}
takeFirstThree([0 ... infinity])
A call-by-name language would hang there trying to create a list from 0 to infinity. A lazy language will simply return [0,1,2].
A simple, yet illustrative example:
function choose(cond, arg1, arg2) {
if (cond)
do_something(arg1);
else
do_something(arg2);
}
choose(true, 7*0, 7/0);
Now lets say we're using the eager evaluation strategy, then it would calculate both 7*0 and 7/0 eagerly. If it is a lazy evaluated strategy (call-by-need), then it would just send the expressions 7*0 and 7/0 through to the function without evaluating them.
The difference? you would expect to execute do_something(0) because the first argument gets used, although it actually depends on the evaluation strategy:
If the language evaluates eagerly, then it will, as stated, evaluate 7*0 and 7/0 first, and what's 7/0? Divide-by-zero error.
But if the evaluation strategy is lazy, it will see that it doesn't need to calculate the division, it will call do_something(0) as we were expecting, with no errors.
In this example, the lazy evaluation strategy can save the execution from producing errors. In a similar manner, it can save the execution from performing unnecessary evaluation that it won't use (the same way it didn't use 7/0 here).
Here's a concrete example for a bunch of different evaluation strategies written in C. I'll specifically go over the difference between call-by-name, call-by-value, and call-by-need, which is kind of a combination of the previous two, as suggested by Ryan's answer.
#include<stdio.h>
int x = 1;
int y[3]= {1, 2, 3};
int i = 0;
int k = 0;
int j = 0;
int foo(int a, int b, int c) {
i = i + 1;
// 2 for call-by-name
// 1 for call-by-value, call-by-value-result, and call-by-reference
// unsure what call-by-need will do here; will likely be 2, but could have evaluated earlier than needed
printf("a is %i\n", a);
b = 2;
// 1 for call-by-value and call-by-value-result
// 2 for call-by-reference, call-by-need, and call-by-name
printf("x is %i\n", x);
// this triggers multiple increments of k for call-by-name
j = c + c;
// we don't actually care what j is, we just don't want it to be optimized out by the compiler
printf("j is %i\n", j);
// 2 for call-by-name
// 1 for call-by-need, call-by-value, call-by-value-result, and call-by-reference
printf("k is %i\n", k);
}
int main() {
int ans = foo(y[i], x, k++);
// 2 for call-by-value-result, call-by-name, call-by-reference, and call-by-need
// 1 for call-by-value
printf("x is %i\n", x);
return 0;
}
The part we're most interested in is the fact that foo is called with k++ as the actual parameter for the formal parameter c.
Note that how the ++ postfix operator works is that k++ returns k at first, and then increments k by 1. That is, the result of k++ is just k. (But, then after that result is returned, k will be incremented by 1.)
We can ignore all of the code inside foo up until the line j = c + c (the second section).
Here's what happens for this line under call-by-value:
When the function is first called, before it encounters the line j = c + c, because we're doing call-by-value, c will have the value of evaluating k++. Since evaluating k++ returns k, and k is 0 (from the top of the program), c will be 0. However, we did evaluate k++ once, which will set k to 1.
The line becomes j = 0 + 0, which behaves exactly like how you'd expect, by setting j to 0 and leaving c at 0.
Then, when we run printf("k is %i\n", k); we get that k is 1, because we evaluated k++ once.
Here's what happens for the line under call-by-name:
Since the line contains c and we're using call-by-name, we replace the text c with the text of the actual argument, k++. Thus, the line becomes j = (k++) + (k++).
We then run j = (k++) + (k++). One of the (k++)s will be evaluated first, returning 0 and setting k to 1. Then, the second (k++) will be evaluated, returning 1 (because k was set to 1 by the first evaluation of k++), and setting k to 2. Thus, we end up with j = 0 + 1 and k set to 2.
Then, when we run printf("k is %i\n", k);, we get that k is 2 because we evaluated k++ twice.
Finally, here's what happens for the line under call-by-need:
When we encounter j = c + c; we recognize that this is the first time the parameter c is evaluated. Thus we need to evaluate its actual argument (once) and store that value to be the evaluation of c. Thus, we evaluate the actual argument k++, which will return k, which is 0, and therefore the evaluation of c will be 0. Then, since we evaluated k++, k will be set to 1. We then use this stored evaluation as the evaluation for the second c. That is, unlike call-by-name, we do not re-evaluate k++. Instead, we reuse the previously evaluated initial value for c, which is 0. Thus, we get j = 0 + 0; just as if c was pass-by-value. And, since we only evaluated k++ once, k is 1.
As explained in the previous step, j = c + c is j = 0 + 0 under call-by-need, and it runs exactly as you'd expect.
When we run printf("k is %i\n", k);, we get that k is 1 because we only evaluated k++ once.
Hopefully this helps to differentiate how call-by-value, call-by-name, and call-by-need work. If it would be helpful to differentiate call-by-value and call-by-need more clearly, let me know in a comment and I'll explain the code earlier on in foo and why it works the way it does.
I think this line from Wikipedia sums things up nicely:
Call by need is a memoized variant of call by name, where, if the function argument is evaluated, that value is stored for subsequent use. If the argument is pure (i.e., free of side effects), this produces the same results as call by name, saving the cost of recomputing the argument.

Resources