How if(some pointer) in C works? - c

I'm a beginner in C and I'm trying to understand the concept of pointer arithmetic:
I have a code like this :
#include<stdio.h>
void main(){
int a[10];
if(a)
printf("%d\n",*a);
}
Which prints the address of first element in array a. That's fine. But in my printf statement I'm using the * operator to print the value.
But when I look at my if statement, I wonder how without * operator, if is working on a?
I mean without * operator, how the if statement accesses the object the pointer points to?
I guess i'm clear enough about my doubt, thanks in advance.

Which prints the address of first element in array a
In your code *a is equivalent with a[0]. You're not printing any address, just some uninitialized value.
EDIT as per comment:
no my question is without * operator, how the if statement accesses
the object the pointer points to
In your code if (a) doesn't access the contents, it only tests the address of a - which will never evaluate to 0.

In C there is no type for a boolean so the body of an if-statement is executed when the condition doesn't equal 0 (zero). And it's quite sure that a doesn't point to the address 0, so the condition evaluates to true.

if (a)
basically checks if a is a null pointer.
When you declare
int a[10]
you allocate a space of memory of 10 integers, starting at the address 'a'.
When you printf *a the compiler prints the first element becuase you're telling it to print the element at the address *(a + offset) which in your case offset = 0;
To convince yourself you can try doing
int *a=null;
if (a)
{
//code here won't be executed because a points to a null reference
}

Related

Accessing array elements in c

Below is the code on compiling this code in codeblocks I get the following error message:
1 value required as increment operator.
Now I know that arr++ is not working but I want to know why.
#include<stdio.h>
int main()
{
int arr[5]={1,2,3,4,5},i;
for(i=0;i<5;i++)
{
printf("%d\n",*arr);
arr++;
}
return 0;
}
arr++ is not working but i want to know why?
arr stores the base address that is &arr[0] therefore, arr always points to the starting position of the array and can't be changed. that's the reason why arr++ is invalid and doesn't work.
Solution:
you can instead use arr with the help of * (referencing operator) operator to print the array elements
for(i=0;i<5;i++)
{
printf("%d\n",*(arr+i));
//pointer arithmetic *(arr+i)=*(&arr[0]+i*sizeof(data_type_of_arr))
}
here, pointer arithmetic is helpful to understand
or else, in order to print the data instead use the index i this way :
for(i=0;i<5;i++)
{
printf("%d\n",arr[i]);
}
One more way to do it is to consider a new pointer to &arr[0] and increment.
int *p=&arr[0];
for(i=0;i<5;i++)
{
printf("%d\n",*p);
p++;
//pointer arithmetic *(p)=*((&p)+1*sizeof(data_type_of_arr))
//NOTE: address of p updates for every iteration
}
For further reading on pointer arithmetic : here
While arrays can decay to pointers to their first element (which is what happens when you use e.g. *arr) it is not a pointer in itself.
You also can not change an array, change where it "points", which is what is wrong with arr++, it is roughly the same as arr = arr + 1 and while arr + 1 is allowed the assignment back to arr is not, you can't change the location of an array.
If you want to do like you do, then you need an actual pointer, initialize it to point to the location of the first element of arr, and use the pointer in the loop instead.
#include<stdio.h>
int main()
{
int arr[5]={1,2,3,4,5},i;
for(i=0;i<5;i++)
{
printf("%d\n",*(arr+i));
}
return 0;
}
arr++ not working.because of array is constant pointer and you can't increment the address. so alway remember array name represent as base address then If you want to increment then give extra argue with that.see the above example.
The increment operator is applied on the value of a variable. The value of an array is its elements, so what would you expect the increment operator to do? Increment each element in the array? The value of a pointer variable, on the other hand, is an address, so the increment operator applies here.
You can't using operator ++ for arrays.
Array is are constant pointer to data and can't be modified.

How does a pointer to the constant pointer of the first element of an array work?

I wanted to test if I could change the constant pointer that points to the first element of an array in C. While testing I got some strange output that I don't understand:
//Constant pointer to pointer to constant value
void test(int const * * const a) {
//printf("%d", **a); //Program crashes (2)
(*a)++;
}
int main()
{
int a[5] = { 1,2,3,4,5 };
test(&a);
printf("%d", *a); //Prints 5 as output (1)
return 0;
}
I expected the compiler to give an error when I try to compile (*a)++ but instead I can run the code, but when I try to print the element I get a strange value (1).
Then I wanted to print out the value (2) of the first element of the array. When I tried this, the program crashes.
By doing &a you are making a pointer to an array (int (*)[]).
Then when this pointer to array is passed to the test function, it's converted to a pointer to a pointer(int **);
Then (*a)++; is UB.
1. So why 5?
On modern implementation of C like GCC, pointer to a array has the same numerical value as the beginning of the array, so is the address value when the array decays to a pointer: they all are the beginning address of the array.
So, in test, int **a points to the beginning of the array, (*a)++ deferences the pointer as int * and increment the pointer by 1 int element, which is usually implemented as adding the sizeof(int) to the numerical value of the pointer.
Then, 1+sizeof(int) gives you 5.
2. Why it crashed in the second case?
Assuming you are using a 32bit x86 machine, or some machine whose pointer type has the same size as int type, then *a equal to 1. Then further dereferencing the pointer at a memory address at 1 usually gives you a segfault.
The program crashes at the printf because test assumes that when it dereferences a the resulting object is a pointer. If it were one and contained a valid address, the second dereferencing would yield an int object. Alas, a contains the address of the array, which is numerically the address of its first element. The 4 or 8 bytes there are considered an address (because test thinks that *a is a pointer) and the code then tries to access the memory at address 1 in order to print the int value assumed at that address. The address is invalid though, so the program crashes.
Now that we have established that the program considers the data at the beginning of the array a pointer to int, we know what (*a)++ does: it increments the value there by sizeof(int) so that the "pointer" point to the next int "element". I guess an int on your machine is 4 bytes long because 1+4=5, which is printed.
This code is illegal in C, you should get a compiler diagnostic. (If not, turn up your warning level). The results of running any executable produced are meaningless.
The code is illegal because int (*)[5] does not implicitly convert to int const **.
the constant pointer that points to the first element of an array in C
There is no such thing. You misunderstand what arrays are. Arrays are a series of contiguous elements. int a[5] is like int a; except that there are 5 ints instead of 1.
int a; and int a[1]; cause identical memory layout. The only difference is the syntax used to access that memory.

Explain how and why the pointer has been used in the following turbo C code

int a[10],sum,*p;
sum=0;
for(p=&a[0];p<&a[10];p++)
sum += *p;
printf("%d",sum)
Hi I'm new in turbo c, especially in pointers. Can someone please explain to me how the pointer was used in this program. Thank you in advance.
I know how the program works, but what I cannot understand is why did the program used a pointer and the '&' sign. Thanks.
This is an illustrative example of Pointers in C, However this code can also be written without using pointers.
Here
p=&a[0]
^ stores the memory address of the First value of the array a.
And the For loop will execute till the Pointer stores the memory address of the last Array value i.e. a[10].
sum += *p;
^ in the above statement *p stands for the value of the memory address to which pointer p points to. For Example p currently points to a[0]. Then the Value of a[0] will be added to sum.
In the next iteration of the For loop, the value of p increases and it will point to a[1].

the difference between array identifier and address of array identifier

Following program would state my doubt clearly I think,so I posted the program:
#include <stdio.h>
int main() {
int a[]={1,2,3,4,5};
if(&a[0] == a)
printf("Address of first element of an array is same as the value of array identifier\n");
if(&a == a)
printf("How can a value and address of an identifier be same?!");
return 0;
}
This is the link to output: http://ideone.com/KRiK0
When it is not the subject of the sizeof or unary & operators, an array evaluates to a (non-lvalue) pointer to its first element.
So &a is the address of the array a, and a evaluates to the address of the first element in the array, a[0].
That the address of the array and the address of the first element in the array are the same is not surprising (that is, they point to the same location even though they have different types); the same is true of structs as well. Given:
struct {
int x;
int y;
} s;
Then &s and &s.x point to the same location (but have different types). If converted to void * they will compare equal. This is exactly analogous with &a and &a[0] (and consequently just a).
C++ has an implicit conversion between an array reference and a pointer. This has been asked many times before, see for example this SO question.
In C, you can get away with comparing two different types of pointers, but your compiler should give you a warning.
If I get your question right. Your int a[]={1,2,3,4,5}; I believe only stores the address of element 0 so putting this if(&a[0] == a)
is probably not required. The c string theory states that an array identifier without the bracket is the address of the first element of the characters. "a" is not defined in the program. it would probably give you a stack error. I would write it this way if(&a == a[]){printf("------"); this would only compare the address of the pointer to the address of the first element of the array.

array of pointers

Consider the following code:
#include <stdio.h>
int main()
{
static int a[]={0,1,2,3,4};
int *p[]={a,a+1,a+2,a+3}; /* clear up to this extent */
printf(("%u\n%u\n%u",p,*p,*(*p))); /* how does this statement work? */
return 0;
}
Also is it necessary to get the value of addresses through %u,or we can use %d also?
Okay, you've created an array of integers and populated it with the integers from 0 to 4. Then you created a 4 element array of pointers to integers, and initialized it so its four elements point to the first four elements of a. So far, so good.
Then the printf is very strange. printf is passed a single argument, namely ("%u\n%u\n%u",p,p,(*p)). This is a comma-expression which means that the comma-separated expressions will be calculated in turn, and only the last one returned. Since the very first thing is a literal, and not an expression, I'd expect it to generate an error. However, without the extraneous parentheses, you have:
printf("%u\n%u\n%u\n",p, *p, *(*p));
This is legal. Three values are passed to printf, interpreted as unsigned integers (which actually only works on some systems, since what you are actually passing in are pointers in the first two cases, and they aren't guarateed to be the same size as unsigned ints) and printed.
Those values are p, *p and **p. p is an array, and so the value of p is the address of the array. *p is what p points to, which are the values of the array. *p is the first value, *(p+1) is the second value, etc. Now *p is the value stored in p[0] which is the address of a[0], so another address is printed. The third argument is **p which is the value stored at (*p), or a[0], which is 0
Do you have an extra pair of parens in your printf statement?
Anyway, you can think of this statement:
printf("%u\n%u\n%u",p,*p,*(*p));
like following a trail of pointers.
p is the pointer itself, printing it should print out the pointer's value which is the address of what it points to. In your case its an array of (int *)'s.
*p is a dereferencing operation. It allows access to the object that p points to. In the other answers you see notes made about *p being equivalent to p[0]. That's because p is pointing to the beginning of your structure, which is the start of the array.
**p is a dereferencing operation on the pointer object that p points to. Extending the example in the previous point, you can say that **p is equivalent to *(p[0]) which is equivalent to *(a) which is equivalent to a[0].
One tip that might help you when trying to decipher these sorts of statements is that keep in mind the precedence rules of C and insert parens between expressions in the statement to break up the statement. For the **p, inserting parens would do this: *(*p) which makes it clear that what you're doing is to follow two pointers to the final destination.
With those extra parentheses, the commas become comma operators so only the final **p is passed to printf. Since printf expects its first argument to be a pointer to a character string, and on most systems pointers
and integers have the same size, so the integer 0 is interpreted as a NULL pointer, and printf prints nothing at all. Or it crashes. That's the trouble with undefined behavior.
Your printf() arguments work like so:
p is an address (it's an array of pointers)
*p is also an address (it's equivalent to p[0], which is just a)
*(*p) is an integer (it's a[0])
My memory on C pointers is a tiny bit rusty, but let me see if I can recall.
p should be a memory location, it points to nothing else, other than p.
*p dereferences (goes to the memory location and returns the value there) p. since p itself is a pointer to pointers (*p[] can be also written as **p) when we dereference p we get the first value in the array definition, or the address of a.
**p dereferences *p. *p is the address of a. If we dereference that, we'll get the value we put in the first location of a, which is 0

Resources