I have the following function which prints a matrix:
void printMat(int* mat, int size)
{
int i;
for (i=0 ; i < size ; i++)
printf("%d ", mat[i]);
printf("\n");
}
Now, suppose I have a certain matrix and I want to implement the print of it by passing it to the function above in three ways:
void main()
{
int mat[2][3] = { {1,2,3}, {4,5,6} };
printMat((int*)mat, 6); //first way//
printMat((int*)mat+1, 6); //second way//
printMat(mat+1, 6); //third way//
}
In the first way, the function actually gets the starting address of the matrix. That I understand.
However, I don't understand why in the first way the function actually gets the address of the second element in the matrix, and not the address of the second line in the matrix (whereas the latter is being implemented actually by the third way).
The reason is the C operator precedence. A cast is stronger than a +
(int*)mat + 1 is the same as ((int*)mat) + 1
so mat is casted to int* before adding 1 (hence you increment a "pointer to int")
Here mat+1 you don't have a cast so it will act like a "row increment" because in this expression mat acts as a "pointer to an array of 3 ints".
BTW: Notice that your code have undefined behavior as it is now.
This has to do with operator precedence.
The (type) operator is ahead of the binary addition operator (+) in precedence.
If you want the second way to be the same as the third way, put
mat + 1 in parenthesis () in the second way.
Then,
printMat((int*)(mat+1), 6); //second way//
will be same as:
printMat(mat+1, 6); //third way//
Related
I wrote a program which returns a determinant of a matrix. I have a problem, actually; it always returns the "0" value. I notice that my determinant always stays as 0 even though I add numbers to it.
I wrote an English translation in the comments to understand my program better. I use a method in which we select one number and then crossed the element from the column and line of the selected number and then calculate the determinant of the uncrossed elements.
#include<stdio.h>
#include<stdlib.h>
float wznmacierz(float*macierz, int rozmiar)/*"macierz" means a matrix and "rozmiar" is a size of matrix */
{
if (rozmiar == 1)
return *macierz;
float *podmacierz = malloc((rozmiar-1)*(rozmiar-1)*sizeof(float)); // making a second matrix for uncrossed elements.
int wyznacznik = 0; // wyznacznik is the determinant of matrix
for(int element_S = 0; element_S <rozmiar; element_S++) //element s is a number from first line
{
for (int w = 1 ; w < rozmiar; w++ ) //line of checking element
{
for(int kolumna = 0; kolumna < rozmiar; kolumna++)//column of chcecking element
{
if(kolumna == element_S)
continue;
*podmacierz = macierz[(rozmiar*w)+(kolumna)];
podmacierz++;
}
}
wyznacznik += macierz[element_S]*( element_S % 2 ? -1: 1)* wznmacierz(podmacierz, rozmiar-1);
}
return wyznacznik;
}
void main()
{
float a[2][2]={{1,3},{9,8}};
printf("%d", wznmacierz(a,2));
}
Change void main to int main, because main returns an int.
In printf("%d", wznmacierz(a,2)); , change %d to %g, because %d is for formatting an int, but wznmacierz returns a float. %g will format a float. Also add \n after %g to complete the line being output.
In printf("%d", wznmacierz(a,2));, change a to *a because wzmacierz expects a pointer to a float, not a pointer to an array of float. This is a kludge to get your program “working” quickly; see Notes below.
You cannot use podmacierz both to hold the start address of the allocated array and to increment to places within the array. Inside the loop on element_S, put float *p = podmacierz; to make a second pointer, and change the uses of podmacierz inside that loop to p.
Before returning from the function, use free(podmacierz); to release the allocated space.
Notes
In main, a is declared as float a[2][2]. This makes it an array of 2 arrays of 2 float. In the call wznmacierz(a,2), a is automatically converted to a pointer to its first element. That produces a pointer to an array of 2 float. However, wznmacierz is declared with a parameter float*macierz, which is a pointer to a float.
One way to fix this is to pass *a. Once a is converted to a pointer to its first element, a pointer to an array of float, then applying * produces the thing that pointer points to, an array of float. Then that array of float is automatically converted to a pointer to its first element, producing a pointer to a float. You could also write wznmacierz(&a[0][0], 2).
This produces a pointer of the correct type for wznmacierz, which then access the array by calculating element locations, using macierz[(rozmiar*w)+(kolumna)]. This nominally calculates correct addresses for the array elements, since arrays are laid out in memory contiguously, but it is bad style unless necessary, and some people might consider it not to conform to the C standard in a pedantic sense.
One fix would be to define a in main as float a[2*2] = {1, 3, 9, 8};. Then the matrix is implemented as single flat array of float everywhere it is used.
Another fix would be to upgrade wznmarcierz to use two-dimensional arrays. A number of changes are needed to do this. I have not tested them, but I think they are at least:
Change wznmacierz(a,2) to wznmacierz(2, a).
Change the declaration of wznmacierz to float wznmacierz(int rozmiar, float macierz[rozmiar][rozmiar]).
Change the use of macierz inside the function from macierz[(rozmiar*w)+(kolumna)] to macierz[w][kolumna].
Change float *podmacierz = malloc((rozmiar-1)*(rozmiar-1)*sizeof(float)); to float (*podmacierz)[rozmiar-1] = malloc((rozmiar-1) * sizeof *podmacierz);.
Remove the float *p = podmaciarz; that I told you to insert above.
Inside the loop using w, insert float *p = podmacierz[w];.
Change macierz[element_S] to macierz[0][element_S].
Change wznmacierz(podmacierz, rozmiar-1) to wznmacierz(rozmiar-1, podmacierz).
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].
I came along a competitive question that asks the output of the following:
#include <stdio.h>
int main()
{
int a[] = {0,1,2,3,4};
int i, *ptr;
for(ptr = a+4, i=0; i <=4; i++)
printf("%d", ptr[-i]);
return 0;
}
I did read this topic: Are negative array indexes allowed in C? However it was unclear to me how the -ve symbol generates the array in the reverse order, ie. 4, 3, 2, 1, 0.
First, recall that in C the expression ptr[index] means the same thing as *(ptr+index).
Now let's look at your expression again: ptr is set to a+4 before the loop; then you apply -i index to it. Therefore, the equivalent pointer arithmetic expression would be as follows:
printf("%d", *(a+4-i));
This expression iterates the array backwards, producing the results that you see.
The reason it works is because the [] operator does pointer addition.
When you reference
a[x]
Whats actually happening is its taking the memory address of a and adding the sizeof(int)*x
So if you set ptr to a+4, you are going to a+sizeof(int)*4
then, when you put in a negative value, you move backwards through the memory address.
ptr[-i] decays into *(ptr + (-i)). At the first iteration, when i = 0, ptr[-i] accesses last element of a array, because initially ptr was set to be equal a + 4, which means - take address of beginning of a and add 4 * sizeof(int) (because ptr was of size int). On every next iteration, when i is incremented, previous element of array is accessed.
In is for statement
for(ptr = a+4, i=0; i <=4; i++)
pointer ptr is set to a+4 It could be done also the following way
ptr = &a[4];
If you tray to output the value pointed to by the pointer as for example
printf( "%d\n", *ptr );
you will get 4. That is the pointer points to the last element of the array.
Inside the loop there is used expression ptr[-i] . for i equal to 0 it is equivalent to ptr[0] or simply to *ptr that is the last element of the array will be outputed.
For i equal to 1 expression ptr[-i] is equivalent to a[4 - 1] or simply a[3]. When iequal to 2 when expression ptr[-i] is equivalent to a[4 - i] that is a[4 - 2] that in turn is a[2] and so on.
SO you will get
4321
a+4 gives a pointer to the fifth element of a. So ptr refers to that location.
Then the loop counts i from 0 up to (and including) 4.
The dereference ptr[-i] is equivalent to *(ptr - i) (by definition). So, since i is 0 and ptr is a+4, it's equivalent to a+4-0, then a+4-1, then a+4-2, and so on until a+4-4, which is (obviously enough) equal to a.
As I mentioned in my comment in C/C++
a[b] == *(a+b) == b[a]
For your case all of these is fine
printf("%d", *(a + 4 - i));
printf("%d", a[4 - i]);
printf("%d", 4[a - i]);
...
new here, trying to learn a piece of C with the great help of you guys, this could be a basic questions here....sorry you have start from basic.
void main()
{
char* arr[3] = {"baba","tata","kaka"};
char* arr1[3] = {"baba1","tata1","kaka1"};
char* arr2[3] = {"baba2","tata2","kaka2"};
char** array_all[] = {arr,arr1,arr2};
printf("%s\n",*array_all[0]);
//please guide me how to access individual entity(as arr[1], arr1[2],arr3[1]) //from each array using array_all
}
I'm not sure if this is exactly what you were looking for.. but this is what I understand so far.
You are wanting to access the individual elements of array_all (the elements arr, arr1 and arr2)? If so then all you do is...
array_all[0][i];
Where i is the element that you want to access.
The reason for this is because the index operators ([ and ]) actually dereferences a pointer and offsets the pointer (as in adds it by some integer, i.e. you move down in memory) that you specify. I recommend reading up on pointer arithmetic if you have no clue what happens if you add a pointer by some integer.
For example:
int x[] = { 1, 2, 3 };
// writing x[i] is the same as *(x + i)
int i = 2; // the element you wish to access
*(x + i) = 4; // set the ith (3rd) element to 4
*(x + 1) = 43; // set the 2nd element to 43
// Therefore...
// x now stores these elements:
// 1, 43, 4
// proof: print out all the elements in the array
for(int i = 0; i < 3; ++i)
{
printf("x[%i]=%i\n", i, x[i]);
}
Also, writing x[0] is the same as writing *x, since the array name actually points to the first element of the array.
OH and one thing, main should actually return an integer result. This is mainly used for error checking in your program, 0 usually means no error occurred and every other error-code (number other than 0) is some specific error related to your program, that you can choose.
i.e.
int main()
{
// e.g. for an error code
/*
if(someErrorOccured)
{
return SOME_ERROR_OCCURED_RETURN_VALUE;
}
*/
return 0; // this is at the end of the function, 0 means no error occured
}
change your printf statement line with this..
printf("%s\n",array_all[i][j]);
In place of i keep your array number and in place of k give your required element number. It works.
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]