negative index in array of pointers in C - c

#include<stdio.h>
int main(){
int a1[]={6,7,8,18,34,67};
int a2[]={23,56,28,24};
int a3[]={-12,27,-31};
int *y[]={a1,a2,a3};
int **a= y;
printf("%d\n",a[0][2]);
printf("%d\n",*a[2]);
printf("%d\n",*(++a[0]));
printf("%d\n",*(++a)[0]);
printf("%d\n",a[-1][1]);
return 0;
}
When I run the above code output is 8,-12,7,23,8. But if i change the last 3 lines to
printf("%d\n",*(++a[2]));
printf("%d\n",*(++a)[1]);
printf("%d\n",a[-1][1]);
output is 8,-12,27,27,7. I'm unable to understand last printf statement. How does a[-1][something] is calculated ? And according to me *(++a)[1] should print 56 instead of 27 !

Pointers and array bases are in fact addresses in virtual memory. In C, they can be calculated into new addresses. Since the compiler knows the size of memory the pointer points to (e.g. int * points to 4 Bytes), a pointer +/- 1 means the address +/- the size (e.g. 4 Bytes for int).
The operator * means to get the value stored in the specified address.
Another trick here is the priorities of the operators. [] is calculated before ++.
If you understand what I mean above, your problem should be resolved.

according to me *(++a)[1] should print 56 instead of 27 !
++a increments a to the next int *, so after it pointed to y[0] equal to a1, it points to y[1] equal to a2. Then [1] in turn designates the next int * after y[1], i. e. y[2] equal to a3+1 (due to the preceding ++a[2]). Lastly, * designates the int which y[2] points to, i. e. a3[1] equal to 27.

Related

What the following code prints / with arrays, pointers etc

I have problem solving this problem, so if anyne had a similar problem it would help me a lot.
short y[2][3]={{0123},{0x12345}},*p=y[1];
printf("01:%x\n", y);
printf("02:%x\n", p);
printf("03:%x\n", sizeof(y));
printf("04:%x\n", sizeof(y[0]));
printf("05:%x\n", sizeof(&y[0]));
printf("06:%x\n", sizeof(*p));
printf("07:%x\n", sizeof(p++));
printf("08:%x\n", *p++);
printf("09:%x\n", *p);
return 0;
Can anyone explain to me why the printout is like this?
01:61ff10
02:61ff16
03:c
04:6
05:4
06:2
07:4
08:2345
09:0
My opinion:
01:Prints the address where the array y begins.
02:Prints the address of the pointer, which points to the second element of the array. Since we have 2 * 3 elements that are of type short, each subsequent element of the zero element will increase by 6.
03:Since we have 2 * 3 elements, which is equal to 6, but the elements of the type are short, so it will print hexadecimal c
04:the number of elements in the zero position is 3, but they are of the short type, so it prints 6
05:prints the sizeof addresses of the first element of the array which is 4
06:I don't know why it prints 2 here
07:Prints the sizeof of the pointer address which is 4, it will increase after printing
08:I do not understand
09:I do not understand
Can anyone explain why it prints like this?
OK, let's see:
#01: The address of y.
#02: The value of p, which holds the address of y[1], which is the second element of type short[3]. The size of a short is apparently 2 on your system, so the offset to #01 is 6.
#03: The size of the array y, 2 * 3 * sizeof (short) give 12, in hex c.
#04: The size of the element y[0], which is of type short[3]. 6, as you found.
#05: The size of the address of y[0], and apparently the size of an address is 4 on your system.
#06: The size of the object that p points to. This is a short, so 2.
#07: The size of the expression p++, which is an address, so 4. And no, p is not incremented, since the expression is not evaluated.
#08: The value of the object that p points to, which is y[1][0]. Since the initializing value of 0x12345 is an int too big to be stored in a short, it is truncated to 0x2345. After reading the value, p is incremented.
#09: The element p points to, which is y[1][1]. It was initialized to 0.
Notes:
You should have got warnings from your compiler:
The mentioned initializer is truncated.
The format for pointers/addresses is %p.
The type of the result of sizeof might not match the format %x.
You should take warnings seriously, they are always a hint that you most probably made an error.
N6) Sizeof(*p) is size of datatype pointed by p. p is pointer to short: so 2 bytes.
N8) p is pointer to short, it`s pointing to array element y[1][0].
y[1] and y[1][0] have the same memory address.
All array elements are short, 0x12345 truncates to 0x2345 upon array initialisation. So output is 2345.
Also, p++ increases pointer value to point to next short y[1][1].
N9) Because of p++ in step N8, pointer now points to y[1][1], which was initialised to 0 (by default, because init value not provided) - output is 0.

When subtracting two pointers in C

I was playing with pointers in order to fully get the concept and then wanted to subtract two pointers expecting the distance between these two addresses or something, but apparently I was wrong, so here is my code.
int x = 5, y = 7;
int *p = &y;
int *q = &x;
printf("p is %d\nq is %d\np - q is %d", p, q, (p - q));
Why does the program output p - q is 1? Thank you.
It is undefined behavior. According to the standard (N1570):
6.5.6 Additive operators
....
9 When two pointers are subtracted, both shall point to elements of the same array object,
or one past the last element of the array object; the result is the difference of the
subscripts of the two array elements.
Note that when allowed, the result is the subscripts difference. So if pointers point to two sequential elements of the same type, the subtraction gives 1, regardless of the size of the type. (This is perhaps the reason why you get 1 in your concrete case.)
Your particular case is cause for undefined behavior since p and q point to unrelated objects.
You can make sense of p-q only if p and q point to the same array/one past the last element of the same array.
int array[10];
int* p = &array[0];
int* q = &array[5];
ptrdiff_t diff1 = q - p; // Valid. diff1 is 5
ptrdiff_t diff2 = p - q; // Valid. diff2 is -5
q - p is 5 in this case since they point to elements of the array that are 5 elements apart.
Put another way, p+5 is equal to q. If you start from p and step over 5 elements of the array, you will point to the same element of the array that q points to.
As an aside, don't use the format specifier %d for printing pointers. Use %p. Use %td for ptrdiff_t.
printf(" p is %p\n q is %p\n p-q is :%td", p, q, p-q);`
// ^^ ^^
See http://en.cppreference.com/w/c/io/fprintf for the valid format specifiers for the different types.
Pointer arithmetic works like that. It doesn't give you differences between two addresses. Instead it will show difference between two variables as if they are stored in an array. so, no matter if your variables (of same type ) are 4 bytes, 8 bytes or 1 byte, if stored in adjacent memory location their pointer subtraction will always result in 1 or -1.
The subtraction of 2 pointers give the distance in between the 2 variables.
For eg.
//let the address of a is 1000 then of a+1 will be 1004
int a[]={1,2,3};
int *p1=a;
int *p2=a+1;
printf("%u",p2-p1);
The result of this will be 1 not 4.
Same here in your case the the location of x and y are consecutive that is why the ans. is 1.
The formula used by pointer substraction is:
( p2 - p1 ) == ( addr( p2 ) - addr( p1 ) ) / sizeof( T )
with T being the type of both p1 and p2.
int array[10];
int* p1 = array + 2;
int* p2 = array + 5;
int* a = p2 - p1; // == 3
int* b = p1 - p2; // == -3
int a=5,b=6;
int *ptr=&a,*diff;
diff=ptr;
printf("%p\n",diff);
ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;
printf("%p\n",ptr);
printf("diff==%td\n",(ptr-diff)*sizeof(int));
(diff-ptr) will provide the distance between two variables, but will not provide the memory gap between two pointers.
Important: only the same type of pointer can be subtracted.
The subtraction of two pointers in array will give the distance between the two elements.
Let the address of first element i.e., is 1000 then address of second element a+1 will be 1004. Hence p1 = 1000 and p2 =1004.
p2-p1 = (1004- 1000) /size of int = (1004-1000)/4 =4/4 =1

%u format Specifier in C

I compiled this code and it gave the the value of '&x' 3 times. That is if &x = 2000 it printed 2036 three times. I want to know the reason for this behaviour assuming an integer requires 4 bytes of memory.
#include <stdio.h>
int main(void) {
// your code goes here
int x[4][3] = {0};
printf("%u %u %u", x+3, *(x+3), *(x+2)+3);
return 0;
}
What will be the output of this code
Anything can happen as the code provokes undefined behaviour by printing a pointer value using the conversion specifier for an unsigned.
To print pointer values use the conversion specifier p.
The address of an array and the address of its 1st element are the same. Pointers to them both however are of different type.
x as well as x + 3 are of type int (*)[3], that is pointing to an array of three ints. Assuming int to be of size 4, an array of three ints is of size 12.
Increasing x (a pointer to int (*)[3]) by three elements one ends up with an address 3 * 12 bytes beyond where x points to. This is called pointer arithmetic.
You're misusing a format specifier and invoking undefined behavior because of that. At that point, what happens is arbitrary and uninteresting.
If you want to print a pointer, use the %p specifier.
x is a pointer to an array of pointers. The array of pointers has 4 elements. Each of these four elements points to 3 integers.
Hence if x = 2000 then,
x[0] = 2000, x[1] = 2012, x[2] = 2024, x[3] = 2036.
Therefore,
x + 3 = 2036 (because x is an array pointer and it increases by 12 each time.)
*(x+3) = x[3] = 2036 again.
*(x+2)+3 = x[2] + 3 = 2024 + 3*4 = 2036 again.
Hence the output will be three same numbers.

Pointers and Addresses in C

The following code manipulates pointers to point at the same location; I'm puzzled about why when I ran the code, the output didn't show value coinciding.
#include "stdio.h"
main()
{
int i=3,*x;
float j=1.5,*y;
char k='c',*z;
x=&i;
y=&j;
z=&k;
printf("\nAddress of x= %u",x);
printf("\nAddress of y= %u",y);
printf("\nAddress of z= %u",z);
x++;
y++;y++;y++;y++;
z++;
printf("\nNew Address of x= %u",x);
printf("\nNew Address of y= %u",y);
printf("\nNew Address of z= %u",z);
printf("\nNew Value of i= %d",i);
printf("\nNew Value of j= %f",j);
printf("\nNew Value of k= %c\n",k);
}
Output:
Address of x= 3219901868
Address of y= 3219901860
Address of z= 3219901875
New Address of x= 3219901872
New Address of y= 3219901876
New Address of z= 3219901876
New Value of i= 3
New Value of j= 1.500000
New Value of k= c
The new address of variable y and z are same. How can two variables have same address and et have different values?
Note: I used gcc compiler on Ubuntu 9.04
What you are printing is not the address of x/y/z, but rather the address they are pointing at. Then, by modifying the pointers (using ++) you eventually get y and z to point at the same address in memory.
Regarding the values - first thing you should notice that you don't actually change the values of j and k, and by the time you print those values the pointers no longer point to them.
Second thing is, even if you did print the value that the pointers point to, you would still get a different value since in one case the data would be interpreted as a float and in the other as a char.
Ah. The dangers of pointer arithmatic.
So y = &j sets pointer y to tha current address of float "j"
then you say y++ as you have defined y as a float pointer this is interpreted as add the length of a float variable to pointer y.
However you have only defined one floating point "j" so y is now pointing at whatever has been allocated after "j" -- in this case it happens to be the address of the "k" variable which was defined immediatly after -- but in practice it could be anything or nothing.
Had you defined "j" as an array of floating points it would have pointed to the second entry in the array equivalent to j[1]. Incendently C will also allow you to use j[1] even though you have not defined j as an array!
Incrementing pointers this way is only useful if your pointer points to an element in an array.
In fact, incrementing a pointer just increases its value by the size indicated by the type of the pointer, so:
incrementing a char-pointer will add 1 to the address
incrementing a long-pointer will add 4 to the address (on systems where a long is 4 bytes)
and so on
Also, while it is not the case in your examples, two variables may (appear to) have the same address but different values.
Assuming that you did:
void display_addr_and_val(const int& var){
printf("Addr:%p Val:%d\n",&var, var);
}
void main(){
int x=0;
int y=1;
display_addr_and_val(x);
display_addr_and_val(y);
}
.. you could theoretically end up with the same address shown for both x and y (if you turn on optimization) . Because the parameter of "display_addr_and_val" is a const reference, the code can be rewritten as:
void display_addr_and_val(const int& var){
printf("Addr:%p Val:%d\n",&var, var);
}
void main(){
int x=0;
display_addr_and_val(x);
int y=1;
display_addr_and_val(y);
}
now, in this version of the code, you may see that there is no overlap in the lifetime of "x" and "y". Which means that in fact the compiler may choose to use the same stack slot for both of them.
Granted, this doesn't happen very often, but there's not theoretical reason why it shouldn't happen - so the bottom line is that you should use extreme caution when you assume anything about the address of variables - especially local ones (e.g. don't assume that their addresses will be allocated in a given order, or that all distinct variables will use distinct addresses)
It's simple pointer math.
the address of the float is incremented at least by sizeof(float), (it should be 4 but you have an increment of 16, it depends on the hardware and the real size used to store floats) while the address of char is incremented by sizeof(char) (1)
you have that y + 16 = z + 1 which is not surprising, remembering that "the next float" (the "things" y now points to) is not indeed a float, but the memory location after the float and so it is for z (it'll point not to a char);
it just means that the float location is 15 bytes "before" the char location. I.e. y + 15 = z.
EDIT: with y I always mean the address of the float taken with &, and so for z...: i.e. before you incrmented them. y+16 is the incremented value of y (after you did y++) and z+1 the incremented value of z after z++.
EDIT 2: dumb me, I did not note that you increment y 4 times! so sizeof(float) is 4, 4*4= 16 ... ! and it is 4 on your machine too (as expected by IEEE for single precision fp numbers...) and so it means that y + (sizeof(float)*4 = z + sizeof(char) ... it still means y location is 15 bytes before z (the address of the char)

Difference between "pointer to int" and "pointer to array of ints"

int main()
{
int (*x)[5]; //pointer to an array of integers
int y[6] = {1,2,3,4,5,6}; //array of integers
int *z; //pointer to integer
z = y;
for(int i=0;i<6;i++)
printf("%d ",z[i]);
x = y;
for(int i=0;i<6;i++)
printf("%d ",(*x)[i]);
return 0;
}
Both the above printfs print numbers 1 through 6.
If both "pointer to array of integers" and "pointer to integer" can do the same thing, do they have the same internal representation?
EDIT: This code does give warnings when compiled as pointed out by the answers below, however it does print the values correctly both the time on my x86_64 machine using gcc
Firstly, your code will not compile. The array has type int[6] (6 elements), while the pointer has type int (*)[5]. You can't make this pointer to point to that array because the types are different.
Secondly, when you initialize (assign to) such a pointer, you have to use the & on the array: x = &y, not just a plain x = y as in your code.
I assume that you simply typed the code up, instead of copy-pasting the real code.
Thirdly, about the internal representation. Generally, in practice, you should expect all data pointers to use the same internal representation. Moreover, after the above assignments (if written correctly), the pointers will have the same numerical value. The difference between int (*)[5] and int * exists only on the conceptual level, i.e. at the level of the language: the types are different. It has some consequences. For example, if you increment your z it will jump to the next member of the array, but if you increment y, it will jump over the whole array etc. So, these pointers do not really "do the same thing".
The short answer: There is a difference, but your example is flawed.
The long answer:
The difference is that int* points to an int type, but int (*x)[6] points to an array of 6 ints. Actually in your example,
x = y;
is undefined** behavior, you know these are of two different types, but in C you do what you want. I'll just use a pointer to an array of six ints.
Take this modified example:
int (*x)[6]; //pointer to an array of integers
int y[6] = {1,2,3,4,5,6}; //array of integers
int *z; //pointer to integer
int i;
z = y;
for(i = 0;i<6;i++)
printf("%d ",z[i]);
x = y; // should be x = &y but leave it for now!
for(i = 0;i<6;i++)
printf("%d ",x[i]); // note: x[i] not (*x)[i]
First,
1 2 3 4 5 6
Would be printed. Then, we get to x[0]. x[0] is nothing but an array of 6 ints. An array in C is the address of the first element. So, the address of y would be printed, then the address of the next array in the next iteration. For example, on my machine:
1 2 3 4 5 6 109247792 109247816 109247840 109247864 109247888 109247912
As you can see, the difference between consecutive addresses is nothing but:
sizeof(int[6]) // 24 on my machine!
In summary, these are two different pointer types.
** I think it is undefined behavior, please feel free to correct my post if it is wrong.
Hope this code helps:
int main() {
int arr[5] = {4,5,6,7,8};
int (*pa)[5] = &arr;
int *pi = arr;
for(int i = 0; i< 5; i++) {
printf("\n%d %d", arr[i], (*pa)[i]);
}
printf("\n0x%x -- 0x%x", pi, pa);
pi++;
pa++;
printf("\n0x%x -- 0x%x", pi, pa);
}
prints the following:
4 4
5 5
6 6
7 7
8 8
0x5fb0be70 -- 0x5fb0be70
0x5fb0be74 -- 0x5fb0be84
UPDATE:
You can notice that pointer to integer incremented by 4 bytes (size of 32 bit integer) whereas pointer to array of integer incremented by 20 bytes (size of int arr[5] i.e. size of 5 int of 32 bit each). This demonstrates the difference.
To answer your question from the title, from the comp.lang.c FAQ: Since array references decay into pointers, if arr is an array, what's the difference between arr and &arr?
However, the code you've posted has other issues (you're assigning y, not &y to x, and y is a 6-element array, but *x is a 5-element array; both of these should generate compilation warnings).
Who knows - this code exhibits undefined behavior:
printf("%d ",(*x)[i]);
Hope this code helps.
#include <stdio.h>
#include <stdlib.h>
#define MAXCOL 4
#define MAXROW 3
int main()
{
int i,j,k=1;
int (*q)[MAXCOL]; //pointer to an array of integers
/* As malloc is type casted to "int(*)[MAXCOL]" and every
element (as in *q) is 16 bytes long (I assume 4 bytes int),
in all 3*16=48 bytes will be allocated */
q=(int(*)[MAXCOL])malloc(MAXROW*sizeof(*q));
for(i=0; i<MAXROW; i++)
for(j=0;j<MAXCOL;j++)
q[i][j]=k++;
for(i=0;i<MAXROW;i++){
for(j=0;j<MAXCOL;j++)
printf(" %2d ", q[i][j]);
printf("\n");
}
}
#include<stdio.h>
int main(void)
{
int (*x)[6]; //pointer to an array of integers
int y[6] = {11,22,33,44,55,66}; //array of integers
int *z; //pointer to integer
int i;
z = y;
for(i = 0;i<6;i++)
printf("%d ",z[i]);
printf("\n");
x = &y;
for(int j = 0;j<6;j++)
printf("%d ",*(x[0]+j));
return 0;
}
//OUTPUT::
11 22 33 44 55 66
11 22 33 44 55 66
Pointer to an array are best suitable for multi-dimensional array. but in above example we used single dimension array. so, in the second for loop we should use (x[0]+j) with * to print the value. Here, x[0] means 0th array.
And when we try to print value using printf("%d ",x[i]);
you will get 1st value is 11 and then some garbage value due to trying to access 1st row of array and so on.
One should understand the internal representation of (*x)[i]. Internally, it is represented as
*((*x)+i), which is nothing but the ith element of the array to which x is pointing. This is also a way to have a pointer pointing to 2d array. The number of rows is irrelevant in a 2d array.
For example:
int arr[][2]={{1,2},{3,4}};
int (*x)(2);
x=arr; /* Now x is a pointer to the 2d array arr.*/
Here x is pointing to a 2d array having 2 integer values in all columns, and array elements are stored contiguously. So (*x)[0] will print arr[0][0] (which is 1), (*x)[1] will print the value of arr[0][1] (which is 2) and so on. (*x+1)[0] will print the value of arr[1][0] (3 in this case) (*x+1)[1] will print the value of arr[1][1] (4 in this case) and so on.
Now, a 1d array could be treated as nothing but a 2d array having only one row with as many columns.
int y[6] = {1,2,3,4,5,6};
int (*x)[6];
x =y;
This means x is a pointer to an array having 6 integers. So (*x)[i] which is equivalent to *((*x)+i) will print ith index value of y.

Resources