Why does using parenthesis make a multi dimentional array behave like this? - c

I accidentally covered the numbers with these instead of the curly brackets normally used and got "2 4 0 0". Why does this shifting happen?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
int a[2][2]={(1,2),(3,4)};
for (int i = 0; i < 2; ++i)
{
/* code */
for (int j = 0; j < 2; ++j)
{
/* code */
printf("%d ",a[i][j] );
}
}
return 0;
}

In the braces of the list initialization in this declaration
int a[2][2]={(1,2),(3,4)};
there are present two expressions ( 1, 2 ) and ( 3, 4 ). They are primary expressions with the comma operator.
According to the C Standard (6.5.17 Comma operator)
2 The left operand of a comma operator is evaluated as a void
expression; there is a sequence point between its evaluation and that
of the right operand. Then the right operand is evaluated; the result
has its type and value
So the values of the expressions are 2 and 4.
Thus in fact you have
int a[2][2]={ 2, 4 };
As a result the first sub-array of the array that is the array a[0] is initialized with these values. Elements of the second sub array a[1] are zero initialized.
If for example you would write
int a[2][2]={(1,2,3,4)};
then this declaration is equivalent to
int a[2][2]={ 4 };
and only the element a[0][0] will be explicitly initialized by the value 4,
Another example of using an expression with the comma operator as an initializer.
int i = 0;
int j = ( i++, i++, i++ );
As a result i will be equal to 3 and j to 2.

You accidentally used the comma operator. In your case it did nothing, but the resulting value from it is the last value in the comma separated list: (1,2) results in the last value 2 and (3,4) results in 4.
So your code was equivalent to:
int a[2][2]={2,4};
The last two of the four values in a were not provided, so they were initialized implicitly with zeroes. This post explains exactly why.

Related

Trying to transpose a matrix in C using pointers

The rest of my code is right I believe but just the transpose part is wrong.
Here's the code for the transpose part:
void transpose(int *m1, int *m2, int n) {
int i = 0;
int j = 0;
while(i=0, i<n) {
while(j=0, j<n) {
*(m1+i*n+j) = *(m2+j*n+i);
j++;
}
i++;
}
}
And here is the results:
M1=
8 1 6
3 5 7 //Original Matrix
4 9 2
M1'=
8 3 4
0 0 0 //Transpose matrix
0 0-71503482
Does anyone know where I went wrong?
This is wrong:
while(i=0, i<n)
It should be:
for(i=0; i<n;)
And of course you can move the i++ and the declaration in there too:
for(int i=0; i<n; i++)
I'd like to elaborate a little bit on John's answer, because it's not clear
whether you understand what this code really does:
while(i=0, i<n)
Here you are using the comma operator.
I'd like to quote Wikipedia:
Wikipedia: Comma operator
[...] the comma operator (represented by the token ,) is a binary operator that evaluates its first operand and discards the result, and then evaluates the second operand and returns this value (and type)
i=0, i<n
will set i to 0, then compare i<n and returns this evaluation as result.
Because n is 3, the condition is evaluated as true and the program enters the
loop. However, every time the condition for the while loop must be evaluated,
i = 0, i<n is executed, thus always setting i to 0 first. In fact you
created an endless loop.

Explain this method of taking input in array [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
for(int i = 1 ; i <= n ; ++i)
{
scanf("%d" , arr + i);
}
explain this method of taking input in array.
Generally, I try this method for entering elements in array.
for(int i = 1 ; i <= n ; ++i)
{
scanf("%d" , &arr[i]);
}
what is the difference between these two methods?``
I found the former one used in competitive programming...
Here is the "normal" way of using scanf to read n elements into an array:
for(int i = 0; i < n; i++)
scanf("%d", &arr[i]);
Note well that I am calling
scanf("%d", &arr[i]);
with an &, so that I pass a pointer to array[i], so that scanf can fill in that element. (One of the surprising things to remember about scanf is that you must always pass it pointers to fill in, unlike printf, where you pass values to print.)
But if we know how pointers and arrays and pointer arithmetic work, we can then see that this alternative form is equivalent:
scanf("%d", arr + i);
The reason is that when when we mention the array arr in an expression like this, what we get is a pointer to the array's first element. And then arr + i is a pointer to the array's i'th element, which is exactly what we want to pass to scanf, as before.
(Also, you'll notice that I have quietly changed your loop from i = 1; i <= n to i = 0; i < n. Arrays in C are 0-based, so you always want your subscripts to run from 0 to n-1, not from 1 to n.)
The thing is, the second is wrong while the first one is correct - but even then the first one is not robust in that - it doesn't check the return value of scanf().
scanf()'s %d format specifier expects an address of int variable. In the second case you provided the int variable itself (if you enabled compiler warnings this would generate warning message) and the first case you provided the address which results in correct behavior.
In case there are n elements then both of the scanf() would invoke Undefined Behavior because you are accessing an array index out of bound. (Arrays indexing starts from 0 in C).
scanf("%d" , arr + i); is equivalent to scanf("%d",&arr[i]). And the correct way to use scanf() would be
if( scanf("%d", &arr[i]) != 1){
// error occured. Handle it.
}
Also from standard:
d
Matches an optionally signed decimal integer, whose format is the same as expected for the subject sequence of the strtol function with the value 10 for the base argument. The corresponding argument shall be a pointer to signed integer.
To be clear on why both are same:-
The arr+i arr converted to pointer to the first element and then with that pointer we add i - in pointer arithmetic every addition is being directed by the type of element it points to. Here the array is containing int elements - which is why arr+i will point to the i th element of the array. arr+i is a pointer to the ith element which is what is expected by %d format specifier of scanf.
Also &arr[i] - here & address of operator returns the address of the element arr[i] or *(arr+i) which is nothing but the address of the i-th element that is what is being expected by %d format specifier of scanf.
Remember that the argument corresponding to %d in a scanf call must be an expression of type int * (pointer to int). Normally, you'd read an array element as
scanf( "%d", &arr[i] );
The expression &arr[i] evaluates to the address of the element, and it has type int *.
The array subscript operation arr[i] is equivalent to *(arr + i) - given a starting address arr, offset i elements (not bytes!) from that address and dereference the result.
This works because in C, an array expression that isn't the operand of the sizeof or unary & operators is converted ("decays") from type "N-element array of T" to "pointer to T", and the value of the expression is the address of the first element.
Thus, the expression arr by itself will ultimately have type int *, and will evaluate to the address of the first element in the array:
arr == (arr + 0) == &arr[0]
Thus, if
*(arr + i) == arr[i] // int
then it follows that
arr + i == &arr[i] // int *
And this is why
scanf( "%d", arr + i );
works as well as
scanf( "%d", &arr[i] );
As a matter of style, use array subscript notation rather than pointer arithmetic. It conveys the intent more clearly. And, you're less likely to make a mistake with multi-dimensional arrays -
scanf( "%d", &arr[i][j][k] );
is easier to write and understand than
scanf( "%d", *(*(arr + i) + j) + k );
Also, check the result of scanf - it will return the number of items successfully read and assigned, or EOF if end of file has been signaled or there's some kind of input error.
Short version: It's the difference between referring to a value and replacing it with input from the user, and referring to a point in memory and writing to it directly.
In C arrays referring to the name of the variable returns the address of that variable in memory.
The scanf() statement takes input from the user and writes it to a specific point in memory. Applying your second method (the one you are using) you should write something like this:
//YOUR EXAMPLE
#include <stdio.h>
#define n 3
int main()
{
int arr[n];
int i;
printf("Input 3 numbers:\n");
for(i = 0 ; i < n ; i++)
scanf("%d" , &arr[i]);
for(i = 0 ; i < n ; i++)
printf("%d",arr[i]);
}
Here you tell your program to get the value of the array in position i, symbolized by arr[i], and replace that value with the new value obtained from the user.
The other example:
//OTHER METHOD
#include <stdio.h>
#define n 3
int main()
{
int arr[n];
int i;
printf("Input 3 numbers:\n");
for(i = 0 ; i < n ; i++)
scanf("%d" , arr + i);
for(i = 0 ; i < n ; i++)
printf("%d",arr[i]);
}
Here we reference the array by name, meaning we reference to the address of the starting point of where that array is stored in memory. In which case, we do not need the '&' symbol, as we are referring an address directly. The '+ i' term means that every iteration of the loop we refer to the next address in memory in that array (skipping sizeof(int) bytes), and so we write directly to that address.
I don't know for sure which is faster, perhaps these are even equivalent to the compiler, perhaps someone else here would have insights, but both ways would work.
NOTE:
I replaced your for loop boundaries, as you were looping from i=1 to i<=n, and writing to arr[i], which means you weren't utilizing the first element of the array, arr[0], and were out of bounds on arr[n]. (The last cell in the array is arr[n-1].

Why postfixed has higher precedence than prefixed? [duplicate]

This question already has answers here:
What is the difference between pre-increment and post-increment in the cycle (for/while)?
(8 answers)
Closed 5 years ago.
Case 1:
int i = 10;
int j = i++;
Here, first the value of i is assigned to j and than i is increased by 1.
Case 2:
int i = 10;
int j = ++i;
Here, first i is increased by 1 and than it is assigned to j.
So, If the operation of increment is done first in the prefixed form, then why postfixed has higher precedence than prefixed?
This has nothing to do with precedence.(here) In pre-increment the value that is assigned is the value before the side effect takes place.
For pre increment it will be the value after the side effect.
int i = 10;
int j = i++;
Before incrementing value of i is 10. So j=10 after these 2 statements are executed.
int i = 10;
int j = ++i;
Here the value will be 11. because incremenet is done first and then it is assigned.
Linux manual page of operator define as same priority for both pre/post increment.
! ~ ++ -- + - (type) * & sizeof right to left
post increment rule is first assigned and then increment
int j = i++;// here first whatever i value is there that will be assigned to j
Pre increment rule is first increment and then assign
int j = ++i;//++i itself will change i value & then modfied value will assign to j.
for e.g consider below example
#include<stdio.h>
int main()
{
int x = 10;
int *p = &x;// assume p holds 0x100
printf("x = %d *p = %d p = %p\n",x,*p,p);
++*p++;
/** in above statement ++ and * having same precedence,then you should check assocaitivity which is R to L
So start solving from Right to Left, whichever operator came first , solve that one first
first *p++ came , again solve p++ first, which is post increment,so address will be same
*0x100 means = 10
now ++10 means = 11
**/
printf("x = %d *p = %d p = %p\n",x,*p,p);
}

How does for(i=0; i<5; x=(i++,a++)) work [duplicate]

This question already has answers here:
What does the comma operator , do?
(8 answers)
Closed 8 years ago.
I can't understand how this works and why it produces
the following output.
int main()
{
int i=0;
int a=5;
int x=0;
for(i=0; i<5; x=(i++,a++))
{
printf("i=%d a=%d x=%d\n",i,a,x);
}
}
this give as output:
i=0 a=5 x=0
i=1 a=6 x=5
i=2 a=7 x=6
i=3 a=8 x=7
i=4 a=9 x=8
Forget about the ++ for the moment, they're just a distraction.
int a = 5;
int i = 0;
int x = (i, a);
Sets the value of x to 5. The i is evaluated and discarded, then the a is evaluated and assigned to x.
In your loop, the post-increment a++ does what it always does; returns the current value and then increments the variable. So x takes the value of a before it is incremented, then a's value is increased by 1. Because i++ was also evaluated, its value increases as well.
I suppose you understand a for loop like this:
for(i=0; i<5; i++)
you might as well want to increment two variables; if you separate them with a comma; like this:
for(i=0; i<5; i++,a++)
at the start of each loop, both i and a will be incremented. Now only the expression x=(i++,a++) needs to be explained:
x gets the last of both values assigned. It is the same as writing:
x=i++;
x=a++;
of course a is post-incremented so first its value is assigned to x; and only then a is incremented.
It is simple both the operators that you have used are 'Post Increment', this means that assignment will happen first then the increment in variable will happen.
Let us understand with an example,
Suppose,
i=5
x=i++;
printf("%d", x)
The above code will give output as 5
and
i=5
x=++i;
printf("%d", x)
and this will give output as 6.
Hope you understand the logic.
The comma operator means: execute all, and return the last value;
Example:
A = (b+=1,c+2,d+1);
This sentence will add 1 to b, sum 2 to c (but will not modify it) and sum 1 to d. Hence d+1 is the last expression A will be set to its value.
The post and pre operator ++ are tricky.
A++ means: return the value of A and after that, you increment it.
++A means: increment A and then return the value of it.
so if A=2
b=A++; // set b to 2 and increments A one unity
b=++A; // increments A to 4 and sets b to 4
Consider your example and the output (except I made the initial value of x to be 22):
int i=0;
int a=5;
int x=22;
for(i=0; i<5; x=(i++,a++))
{
printf("i=%d a=%d x=%d\n",i,a,x);
}
Prints:
i=0 a=5 x=22
i=1 a=6 x=5
i=2 a=7 x=6
i=3 a=8 x=7
i=4 a=9 x=8
Notice that x has either the initial value of x prior to the loop or the previous value from the last trip through the loop.
Recall that any for loop can be expressed as an equivelent while loop.
The for loop of:
for(exp 1; exp 2; exp 3){
expressions
}
Is equivalent to:
exp 1;
while(exp 2){
expressions
exp 3;
}
So your for loop can be written as:
int i=0; // exp 1 from the for loop
int a=5;
int x=22;
while(i<5){ // exp 2
// loop body
printf("i=%d a=%d x=%d\n",i,a,x);
x=(i++,a++); // exp 3 from the for loop
}
Prints same output.
The fact that exp 3 is evaluated at the end of the loop (whether it is a for or while loop) is why x has the previous value of x in the body of the loop.
The final thing to consider is the comma operator. The expression:
i=(a+=2, a+b)
^^^ evaluate a then add 2
^ comma operator in this case
^^ add b to a
^ store the final expression -- the RH of the comma operator --
into i

pointer movement what is difference between cs[1], and *cs++

I am trying to understand how the pointers are moving.
Following is the program and I am aware that
if
int cs={1,2,3};
then cs points to cs[0]
what I am not clear is what is *cs pointing to.
#include<stdio.h>
int main()
{
int array[] = { 1, 2, 3, 4, 5 };
int *arrptr1 = array;
int *arrptr = array;
int i;
for (i = 0; i < sizeof(array) / sizeof(int); i++) {
printf("%d, %d, %d\n", array[i], *arrptr1++, *arrptr + i);
}
}
the output of above program is
1, 1, 1
2, 2, 2
3, 3, 3
4, 4, 4
5, 5, 5
then my understanding *arrptr should increase the value stored at
*arrptr
should get incremented by 1.
Where as what I observe is the pointer is moving to next location.So just want to know what is wrong in my understanding?
UPDATE
As per the replies below I understand that
print("%d", *arrptr1++);
in such a statement evaluation of operators is from right to left.
Hence in *arrptr1++ the ++ will get evaluated first and then arrptr and then *
So to confirm the same I wrote another program
#include<stdio.h>
int main()
{
int array[] = { 10, 20, 30, 40, 50 };
int *q1 = array;
printf("q1 = %p\n",q1);
printf("*q1++ = %d\n",*q1++);
printf("q1 = %p\n",q1);
printf("*q1++ = %d\n",*q1);
}
The output of above program is different than the expected operator precedence by above logic.
The output I got is
q1 = 0x7ffffcff02e0
*q1++ = 10
q1 = 0x7ffffcff02e4
*q1++ = 20
So I was expecting in the 2nd line of output instead of *q1++ = 10 following *q1++ = 20
so did the operator precedence not happened right to left?
*arrptr1++ is parsed as *(arrptr1++), not (*arrptr1)++.
Whenever you use dereference operator * and pre-increment(pre-decrement) or post-increment(post-decrement) operator on a variable simultaneously ,the order of operation is from right to left (if parenthesis are not used).
What you want to do is
(*arrptr)++
because of higher precedence of (), it will force the compiler to first access the element pointed to by arrptr and then increment its value.
When you do this *arrptr++ , as I've said it first operates rightmost operator (i.e. ++)
and then the dereference operator.
If you will write
EDITED (only the comment): *++arrptr // increment the pointer then access
it will first advance the pointer and then access the value
stored in the address now pointed to by arrptr.
One more thing,The comma used for separation of function argument is not the comma operator so the order of evaluation of the arguments is undefined. (already been told)
What happens is that *arrptr1++ is interpreted as *(arrptr1++), which means that the pointer to the array is increased by one each time in the loop, and hence it will point to the same element as array[i]. *arrptr + i on the other hand is interpreted as "the value of the array element pointed to by arrptr plus the integer i". In this loop it means it will display the same thing as array[i], but it is not pointing at the same element (arrptr is always pointing to the first element in your array). If you change the values in the array to something more random, it should be obvious when you run the program again.
cs = &cs[0] ( cs is equal to the address of cs sub 0) ; *cs = cs[0] (cs pointer is equal to cs sub 0) ; You should remember that *'s hide the [].
// here is a print function with a pointer
int foo[5] = { 2, 9, 1, 3, 6};
int *walker, count;
walker = foo;
for (count = 0; count < 5; walker++, count++)
printf("Array[%d]: %d\n", count, *walker);
Recap: walker is equal to &foo[0], so when you increment walker (eg. walker++) you're moving the pointer to the next address which is foo[1]. And when we are printing the value we can't say ..., walker); since walker( &foo[whatever] ) is pointing to an address, we need to dereference the pointer to get the value. Again, the most important thing to remember
array = &array[0] AND *array = array[0]

Resources