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
Related
This question already has answers here:
C - how to convert a pointer in an array to an index?
(1 answer)
Pointer subtraction confusion
(8 answers)
Do pointers support "array style indexing"?
(1 answer)
Closed 3 years ago.
This is my code, which can find highest number in an array by the pointer.
#define ELTS 5
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int i, *high, *p;
int array[ELTS]={200,34,78,600,45};
high=array;
p=array;
for ( i=1; i< ELTS; i++ ) {
p++;
if (*p > *high) high = p;
}
printf("the highest number is %d \n", *high);
printf("at address %p \n", high);
printf("index %ld \n", high);
printf("index %ld \n", array);
printf("at index %ld of array \n", high-array);
exit(0);
}
I also need to find the index number of this number, I did some research online. and find out I can use printf("at index %ld of array \n", high-array); to get the index of the highest number.
However, I don't understand how that works, can anyone explain it to me?
In high-array, high is the address of the element you are interested in, and array is the address of the first element in the array. (array actually identifies the array, but, when used in this expression, it is automatically converted to the address of the first element.) Then, with the - operator, the two addresses are subtracted.
When addresses are subtracted, C produces a result measured in units of array elements. So, even if the array addresses are measured in bytes, the compiler computes a result by subtracting the pointers (to get the difference in bytes) and then dividing by the number of bytes in an element (to get the difference in elements).
Thus, the result of high-array is the number of elements from the start of the array to the element pointed to by high, and that is the index of that element.
(In some C implementations, the pointers might not be measured in bytes and might not be simple one-number addresses. Regardless, the C implementation performs whatever operations are necessary to produce a result that is a number of elements.)
Notes
To print pointers, convert them to void * and print them with %p:
printf("index %p \n", (void *) high);
To print the difference of two pointers, use %td:
printf("at index %td of array \n", high-array);
Use the pointer arithmetic. The index is calculated like
high - array
The difference contains the number of elements of the type int between these two pointers.
Consider for example this statement from your program
p++;
After this statement the pointer points to the next element of the array. This statement can be rewritten like
int *q = p;
p = p + 1;
So p - q is equal to 1.
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].
int n;
scanf("%d",&n);
int *score;
score=(int *)malloc(sizeof(int)*n);
int i;
for (i=0;i<n;i++)
{
scanf("%d",sizeof(int)*i+score);
}
printf("ok");
In the above code I get an error but when I comment the last line printf the program runs correctly.
what is the problem??
(I want to give n number from user without using arrays)
Pointer arithmetic of the form score + i is already done in multiples of sizeof(*score). So when you write score + i * sizeof(int) you doubly multiply by the size of the items. You reach way beyond the bounds of the buffer.
Either write it simply as score + i, or if you insist on doing the multiplication yourself, be sure to cast to a character pointer type first:
(int*)((char*)score + i * sizeof(int))
Oh, and don't cast the result of malloc. C doesn't require it, and it's somewhat unidiomatic.
scanf("%d",sizeof(int)*i+score);
pointer arithmetic uses the pointer type, so here you are moving to sizeof(int)isizeof(int) bytes after score, instead just use scores+i.
int akki(int arr[],int m,int n){
int i;
for(i=0;i<m;i++){
if(arr[i]==n)
return i;
}
return 20;
}
void main(){
int i,m,n,arr[10],a;
printf("Enter size of array:");
scanf("%d",&m);
printf("Enter %d elements of array:",m);
for(i=0;i<m;i++){
scanf("%d",arr[i]);
}
printf("Enter element to be searched:");
scanf("%d",&n);
a=akki(arr,m,n);
if(a!=20)
printf("Element found at %d position",a+1);
else
printf("Element not found");
}
IT is Returning 20 or some garbage value..even if condition matches... it is returning value of i.It is linear search function where m is size of array arr and n is element to be searched...
please explain in detail..i am new in c language
thankzzz in advance
You have a problem in your code. Change
scanf("%d",arr[i]);
To
scanf("%d",&arr[i]);
This is done because scanf expects an argument of type int* but you provide argument arr[i] which is of type int. Also add a check that ends the program if user inputs a number which is greater than 10 for the first scanf.
There can be two reasons.
Case 1 [Much likely for _always_]
Simple. Because your if(arr[i]==n) condition is not met, and i<m became false. It came out of for() loop and hence, return 20.
case 2 [Less likely for _always_]
By chance, the value of n is present at the 21st location [index 20] in the input array.
Apart from the coding aspect, did you understand what's the logical purpose of this function? If not, begin with that. It searches for a specific value in an array of given length, and if no element of the array matches that value, it returns 20.
Now analyze your case, based on your input.
EDIT:
After seeing the complete code, as Mr. CoolGuy has pointed out, use
scanf("%d",&arr[i]);
Just for more reference, you can look at Chapter 7.19.6.2, paragraph 12 , %d format specifier, which goes like
... The corresponding argument shall be a pointer to signed integer.
In your code, arr[i] is of type int. What you need is a int *, i.e., &arr[i].
This is not homework, but my last assignment made it clear that I didn't clearly understand pointers when coding C.
Therefore, I tried to type a simple program using pointers just to invert an integer in a function, so I could figure out where the gap in my understanding is.
Apparently, I've arrived at it, but I still cannot figure out what I am doing wrong.
My source code is below.
#include <stdio.h>
float invert(int *num);
void main (void)
{
int num;
float a;
printf("enter an integer \n");
scanf("%i", &num);
printf("Number entered %i \n", num);
a=invert(&num);
printf("This is the invse from main %f \n", a);
}
float invert(int *num) /* function inverts integer */
{
float invse;
printf("num is %i \n\n", *num);
invse = 1/(float)num;
printf("invse is %f \n\n", invse);
return(invse);
}
My thinking was that I used the pointer to direct the computer to use the value stored at the address for num in the function invert(). The pointer appears in the variable declaration. I cast the value stored at that pointer as a float, so I could invert it, and store it in a local variable.
The problem appears to be in the local variable assignment. My compiler returns "invert.c:29:2: error: pointer value used where a floating point value was expected
invse = 1/(float)num;
^
Apparently my code indicates a pointer value for inverse, but I declared it as a float, which I find confusing.
Any help is appreciated. This will save me on completing my larger set of code for my assignment, which I did not post here.
Thanks.
Judging by the printf call inside invert
printf("num is %i \n\n", *num);
you already know that in order to access the value passed to invert for inversion you have to dereference num pointer: *num.
If so, then why aren't you dereferencing num when you perform the inversion itself?
invse = 1/(float)num;
I mean, if you are the one who wrote that printf, you should also realize that the actual inversion should be done as
invse = 1 / (float) *num;
or, alternatively, as
invse = 1.f / *num;
On top of being incorrect your original variant is illegal: you are not allowed to convert pointers to floating-point types in C, which is the reason for the error message.
P.S. From the bigger picture point of view, there's no real reason to pass that the number to invert by pointer. Passing the immediate value would make more sense
float invert(int num)
{
...
In that case you, of course, don't have to dereference anything inside invert.