Can I use scanf with pointers? - c

This week my teacher of C language explained that we can use * (array + i) rather than array [i], he also mentioned the advantages of using this "new method". It's ok so far and then he gave us some exercises to do, in one of them I'm trying to use along with scanf this new method.
I know how to do it like this:
printf("%i", *(array + i));
My doubt is, how can I use *(array + i) in an scanf, or it's not possible?
scanf("%i", *(array + i));
for(i = 0; i < size; i++)
{
printf("Insert number: %i", i+1);
scanf("%i", *(array + i); // it's not working.
}

The argument to scanf must be a pointer to the variable you want to store the result in, so you shouldn't dereference it:
scanf("%i", array+i);
This is simply the opposite of the way you deal with ordinary variables in printf() and scanf():
printf("%i", var);
scanf("%i", &var);
Adding & is analogous to removing *.

*(array + i) == array[i]
array + i == &array[i]
This means:
printf( "%i", array[i] ) == printf( "%i", *(array + i) );
scanf( "%i", &array[i] ) == scanf( "%i", array + i );
he also mentioned the advantages of using this "new method"
What advantages would those be? In my experience, using *(a + i) over a[i] tends to result in code that's less clear, and easier to get wrong.

In C, a[i] actually gets translated to *(a+i); it's called syntactic sugar
Arrays are referenced using their variable names and individual array elements are referenced as the starting address + (element position*size of each element)
As mentioned in the Barmar's Answer - you should be using
a+i instead of *(a+i)
because the scanf function needs an address as argument to store the input, not the dereferenced value

Indeed, you have to use scanf(3) with pointers, as it is not allowed to pass a nonpointer value. But what you cannot do (except if the final pointed value is also a pointer) is to use them with dereferenced pointers (what is indeed done in your example, when you write *(array + i)) If you want to use the pointer you can for example, pass array + i which is a perfectly valid pointer, that points to the i-esim element of array.

Related

Why is not ampersand needed in the following code?

I understand that in C programming, 'scanf' is used with '&' for all variable tyles (int, float, char, ..) except string. Here is my program code. In front of 'scanf', why isn't '&' needed? And may I know more about scanf?
#include <stdio.h>
#define M 10
int main()
{
int i, n, sum = 0;
int a[M];
do{
printf("Input a positive number less than %d \n",M);
scanf("%d", &n);
}while (!(n >0 && n < M));
printf("Input %d numbers \n",n);
for(i=0; i<n ; i++){
scanf("%d",(a+i));
sum += *(a+i);
}
printf("Sum = %d \n",sum);
}
Because you have declared a as an array, an expression using that variable's name, on its own, will usually 'decay' to a pointer to the first element of the array (What is array decaying? - but see also the excellent comment added by Eric Postpischil for exceptions). This is similar to using a char[] string where, as you correctly noted, you don't need to use the & operator when passing it as an argument to scanf.
Adding i to this 'base address' of the a array will give the address of (i.e. a pointer to) the 'i'th element of the array.
Here is a decent tutorial on pointer arithmetic in C that you may find useful.
scanf usually takes the address of a variable it's reading into. a is already an address (an array that's decayed to a pointer) and i is simply an offset from that address.
This is equivalent to scanf("%d", &a[i]);; it does the same thing.
The & operator used before a variable in c returns the address of that variable. The base of an array already is the address you want. a+i like you're doing is using pointer arithmetic and changing the base address of the array by i

implementing a function with matrix - differences

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//

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].

C Compare array elements using pointers

I'm trying to make a program to compare array elements using pointers and to give me some result; I make this simple program just to test if it works but I don't know why.. if i enter equals numbers nothing happes. So the first variable of the array is ptr so ptr + 1 means the next element, if i enter directly ch[0] == ch[1] it works. After that I want to make the program to compare characters if are the same.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int main()
{
int ch[2];
int *ptr = &ch;
scanf("%d%d", &ch[0], &ch[1]);
printf("Numbers to compare %d and %d", *ptr, *ptr + 1);
if (*ptr == *ptr + 1){
printf("Equals numbers\n");
}
return 0;
}
Always remember a quick rule.
If the elements are i th and i+1 th index of some array, the the way to access them without using pointer is
a[i] & a[i+1]
Now if you want to get the address of these values without using pointer, then you do &a[i] and &a[i+1]
Now if you want to perform the above two tasks with pointer, then remember array name itself is a pointer to it. So if you want to get the address of i th and i+1 th element, the it will be simply
(a + i) and (a + i + 1)
Now if you want to get the values at these locations, then simply de-reference it like
*(a + i) and *(a + i + 1)
That's why in this case, it will be *ptr == *(ptr + 1)
Note: &a[i] is equivalent to (a+i)
and a[i] is equivalent to *(a+i)
Note 2: If you are not using Turbo C in windows system, then it is not recommended to use conio.h because it is not platform independent. I recommend you to move from Turbo C & conio.h
To explain #kaylum comment which is correct:
You had if (*ptr == *ptr + 1) now the *ptr part is correct but the right hand side of the == is incorrect because the way you have it your dereferencing ptr and then adding one to that value. However you want to increment ptr and then dereference hence why you need the ()
you are making mistake
int *ptr=&ch;
*ptr == *ptr + 1
printf("Numbers to compare %d and %d",*ptr,*ptr+1);
replace it with *ptr=ch becoz ch is an integer array so if you assign it directly to *ptr it will return the first address of ch i.e ch[0] address will be return
difference between using *ptr+1 and *(ptr+1)
*ptr+1 is similar to ch[0]+1 and *(ptr+1) is similar to ch[1]
you are doing *ptr+1 this will increment your first position of array ch so your output will Number to compare 1 and 2 even if your input is 1 and 5 replace it with *(ptr+1)

Using negative number as array index

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]);
...

Resources