Pointer subtraction on void elements - c

EDITED: Basically, I am trying to determine in a vector, being given one element, what the next element is. The elements are contiguous. The expression below is supposed to pass the first element as the previous element, and it should return a pointer to the second element. I want the distance to return the difference b/w the previous pointer and the first pointer to find where the second element is...
I have this expression:
int next = *(char *)v_next(vec, vec_first(vec));
Then in the function being called, I have this line in order to determine the position of one pointer from another..
void *v_next(const vector *vec, const void *previous) {
...
void *first = cvec_first(cv);
int distance = (char*) &previous - (char*) &first;
However, when I compare the first element and the second element, it returns a distance of 32. If I divide this distance by char*'s size, I get 8. That's clearly way too many bytes to separate one pointer from another and therefore this expression doesn't work out to find the right position...
next = (char*) vec->elems + vec->elemsz + distance;
How can I get the subtraction working properly?

The thing is that you need to substract pointers of proper "undecayed" type (whatever it is in your case). See following example:
#include <stdio.h>
int main(void)
{
int a[] = {1, 2, 3, 4, 5}, *p, *q;
p = a;
q = a + 1;
printf("Corect distance: %d\n", (int) (q - p));
printf("Incorrect distance: %d\n", (int) ((char *)q - (char *)p));
return 0;
}
Note that p and q have to point into the same array, or more precisely (C99 6.5.6 Additive operators):
[...] 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.
otherwise it's UB. The result of substaction has implementation-defined type ptrdiff_t (that's why I casted result to int).

You're comparing the wrong pointers. &first is the location of the variable first, which is a local variable. Same for &previous. So you're comparing two pointers that has nothing to do with what's in the vector.
From your third statement it looks like you want the offset in bytes. You shouldn't divide it by anything if so. It's given by:
int distance = (char*)previous - (char*)first;
(note that you might want to use ptrdiff_t instead of int depending on your architecture.)
Your statement for next should then work, but it should also be the same as:
next = (char*)previous + vec->elemsz;
I've tried that, but when I use the expression beginning with "int next" above, it only prints 0.
That's because of your first line, where you're only reading a single byte (char):
int next = *(char *)v_next(vec, vec_first(vec));
^^^^^^^^^
You're casting to the wrong type here. You want to cast to the type that's stored in the vector, which I'm guessing is int. So it should read:
int next = *(int *)v_next(vec, vec_first(vec));

Related

Can you add an array without square brackets or subscript to an integer? What is the result?

I was going through an online lecture and I saw this function to sum an array
int arraySum(int array[], const int n)
{
int sum = 0, *ptr;
int *const arrayEnd = array + n;
...
}
I've not seen an array added to an integer before. If n is the size of the array, does array + n mean that arrayEnd is assigned a value of the last element in array[] or does it mean something else like the address of that element?
What you're seeing is pointer arithmetic.
array is a pointer to the start of your array. Assuming the array has n elements, then array + n (or equivalently &array[n]) points to one element past the end of the array.
It is legal to have a pointer to one element past the end of an array, however you can't dereference that pointer.
void f(int array[]) and void f(int* array) are the same thing in C. So you're almost right when you speculate that it's the address of the last element: it's one past that. Meaning it's useful for less than checks, but not to dereference as that might crash or result in a garbage value.

Why difference between pointers to two consecutive array entries is always 1, if not cast to char pointer?

What is the point of typecasting into char ? Why not typecast it in int instead ?
#include <stdio.h>
int main()
{
int arr[15];
arr[1]=5;
arr[0]=2;
int diff = (char *)&arr[1] - (char *)&arr[0];
int diff2 = &arr[1] - &arr[0];
printf("%d\n%d", diff, diff2);
return 0;
}
Pointer arithmetic is not for the weak of heart, but always this will be true:
(&arr[0]/* pointer to first element*/)
+
(1 /* "next" */)
==
(&arr[1]/* pointer to second element*/)
This is true for any type, it is part of the rules of pointer arithmetic.
So it cannot be any other than
(&arr[1]/* pointer to second element */)
-
(&arr[0]/* pointer to first element */)
==
1
which is of course exactly like
diff2 == 1
This is not changed if the result of & is cast to a pointer to the actual type of the array entries, in this case int and int*. With that +1 still means "next array entry".
On the other hand
(char *)&arr[0]
is bend to be a pointer to something different than the type of the entries of the array. It has been forced to be a pointer to a char. If you increase that by one, it has to be a pointer to the next char and
(char *)&arr[0] + N
==
(char *)&arr[1]
can only be true, if N is the number of chars between the addresses of two consecutive array entries.
So
N =
(char *)&arr[1] - (char *)&arr[0]
ensures it.
To understand this let us take a simple example:-
#include <stdio.h>
int main()
{
int arr[3]={1,2,3};
int *p=arr;
for(int i=0;i<3;i++){
printf("%d ",*p);
p++; // In this line p is an address.
//Here address is incremented by 1.
// But the logic is that 1 is an integer.
// If 1 might not be an integer then the result should not be like this.
// Same is in your case if you are storing difference of two addresses
// in an integer then it calculates the difference
// with respect to the type of address(int in your case).
}
return 0;
}
In c++ if integer is used with addresses for any operation then its calculations are totally based upon the type of address(int,void,float....).

pointer to two-dimension array

typedef char trgm[3];
char test[2][3] = {'a','b','c','d','e','f'};
int main(void)
{
trgm *t;
t = test;
printf("%c\n",*(char *)t);
printf("%c\n",*(char *)*t);
printf("%c\n",**t);
return 0;
}
the output of three printf is same. I don't understand why the t and *t are same? what does complier do internal?
There are three paths of interpretation of the same value - the starting address of the memory extent occupied by the array. So dereferencing the value casted to char * you will get the value of the first element of the type char of the array.
You can think of an array variable as containing the memory address of its first element. In your case since the array is a 2D array, the "first element" t[0] is in-fact pointer to the 'first row'. Note that in terms of memory there is no special storage for element t[0] and t[1], it gets converted to appropriate memory offset, but it helps to think that way. Hence when you deference the pointer (*t), you get the same value as you would get for the array variable.
t = [0] --> 'a','b','c'
[1] --> 'd','e','f'
Try this printf("%p %p %p\n", t,*t, t[0]);, you will get same value for all.
When you declare the typedef char trgm[3];, then trgm refers to *an array of char [3]`. This is important.
When you declare trgm *t = test, the pointer t is a pointer to array of char [3]. By setting t = test; you make t a pointer that points to the first row of test (essentially equivalent to test[0]. Since an array variable holds (or points to) the first element of test, both t and test point to the same value. Dereferncing the either the pointer t or test (e.g. *t or *test) will access the first element of test.
Now since t is a pointer to array of char [3], it is a pointer with two-levels of indirection and can therefore be dereferenced twice (as can test). Take test[row][col]. Let's look at the pointer equivalent for the array. test can be written as
*(*(test + col) + row)
(both col and row are 0 when referencing the first element (e.g. test[0][0]) so the above is simply
*(*(test + 0) + 0)
note: anything plus 0 is just that thing again, so it simplifies to:
**test
For t it is just:
(*t)[col] /* to index cols 0 - 2 */
It too can be rewritten as:
*((*t) + col)
With col being zero for the first element, you get
**t
However, t by pointing to the first row, allows pointer arithmetic (e.g. t = t + 1;, or just t++) to update t to point to the second row, and so on.
So, in sum, whether you are looking at test or you are looking at t, both initially reference the address for the first element in test, both are (or can be considered) pointers with two levels of indirection, and dereferencing each once, or twice, will still point at the original element in test. You can use t to access all values in your array, for instance:
for (; t < &test[2]; t++)
printf (" %c, %c, %c\n", (*t)[0], (*t)[1], (*t)[2]);
putchar ('\n');
Which will output:
a, b, c
d, e, f
Lastly, there is no need to make test a global variable. Avoid global variables to reduce the chance of name collision. Declare test in main() and pass it pointer to it to any other function it is required.
Putting that altogether, you could do something like:
#include <stdio.h>
typedef char trgm[3];
int main(void)
{
char test[][3] = {{'a','b','c'},
{'d','e','f'}};
trgm *t;
t = test;
printf("%c\n",*(char *)t);
printf("%c\n",*(char *)*t);
printf("%c\n",**t);
for (; t < &test[2]; t++)
printf (" %c, %c, %c\n", (*t)[0], (*t)[1], (*t)[2]);
putchar ('\n');
return 0;
}
Example Use/Output
$ ./bin/p2x3
a
a
a
a, b, c
d, e, f
Look things over and let me know if you have any further questions.

How do you get the address of array elements given the address of the array itself in C?

*edited to clarify that the array is unknown
If the address of unknown integer array is 0x00006ffd29c78e70 (and an integer is 4 bytes), what is the address of element array[1]?
Many thanks in advance.
The address of the array is also the address of its first element. This is because the array itself in memory consists solely of each of its elements (starting at index 0) in turn. Therefore if A is an array, &A[0] points to the same memory as A. (Note that there is a technical difference between an array of integers type and a pointer to an integer type, though they are in many cases interchangeable as the former decays into the latter under certain circumstances which are beyond the scope of this question; this is why I described them as pointing both to the same memory).
You asked about the first element, and then referred to A[1]. Note that A[1] is the second element. A[0] is the first element.
So in your particular example, you could do:
int *A = (int *)0x00006ffd29c78e70;
int *A1 = &A[1]; // points to second element
int foo = *A1; // second element contents
or using pointer arithmetic
int *A = (int *)0x00006ffd29c78e70;
int *A1 = A+1; // points to second element
int foo = *A1; // second element contents
Note the +1 does not add one to the (byte) address, but increments the pointer by one int.
Note I have written int above - use the correct integer data type to represent your 4 byte integer.
If 0x00006ffd29c78e70 is the address of a valid array of ints then you can assign it to a pointer:
int *p = (int*)0x00006ffd29c78e70;
then p[1] will give you the next element (second) in that array.
Elements are at
unsigned char *addressofarray = whatever;
unsigned char *secondelement = addressofarray + sizeof arrayelement;
unsigned char *nthelement = addressofarray + n * sizeof arrayelement;
you just got a pointer to acess any thing in array as:
int *ptr = (int*) 0x00006ffd29c78e70;
you can acess any element as:
*(ptr+i) //i is the index

What is the difference between pointer to array and pointer to pointer?

I'm new in programming and learning about pointers in array. I'm a bit confused right now. Have a look at the program below:
#include <stdio.h>
int fun();
int main()
{
int num[3][3]={23,32,478,55,0,56,25,13, 80};
printf("%d\n",*(*(num+0)+1));
fun(num);
printf("%d\n", *(*(num+0)+1));
*(*(num+0)+0)=23;
printf("%d\n",*(*(num+0)));
return 0;
}
int fun(*p) // Compilation error
{
*(p+0)=0;
return 0;
}
This was the program written in my teacher's notes. Here in the main() function, in the printf() function dereference operator is being used two times because num is pointer to array so first time dereference operator will give pointer to int and then second one will give the value at which the pointer is pointing to.
My question is that when I'm passing the array name as argument to the function fun() then why *p is used; why not **p as num is a pointer to array?
Second thing why *(p+0) is used to change the value of zeroth element of the array; why not *(*(p+0)+0)=0 as in the main() function *(*(num+0)+0) is used to change the value of zeroth element?
The whole thing is very confusing for me but I have to understand it anyway. I have searched about this and found that there is a difference between pointer to array and pointer to pointer but I couldn't understand much.
The trick is the array-pointer-decay: When you mention the name of an array, it will decay into a pointer to its first element in almost all contexts. That is num is simply an array of three arrays of three integers (type = int [3][3]).
Lets analyse the expression *(*(num + 1) + 2).
When you mention num in the expression *(num + 1), it decays into a pointer to its first element which is an array of three integers (type = int (*)[3]). On this pointer pointer arithmetic is performed, and the size of whatever the pointer points to is added to the value of the pointer. In this case it is the size of an array of three integers (that's 12 bytes on many machines). After dereferencing the pointer, you are left with a type of int [3].
However, this dereferencing only concerns the type, because right after the dereferencing operation, we see expression *(/*expression of type int[3]*/ + 2), so the inner expression decays back into a pointer to the first array element. This pointer contains the same address as the pointer that results from num + 1, but it has a different type: int*. Consequently, the pointer arithmetic on this pointer advances the pointer by two integers (8 bytes). So the expression *(*(num + 1) + 2) yields the integer element at an offset of 12 + 8 = 20 bytes, which is the sixth integer in the array.
Regarding your question about the call of fun(), that call is actually broken, and only works because your teacher did not include the arguments in the forward declaration of fun(). The code
int fun(int* arg);
int main() {
int num[3][3] = ...;
...
fun(num);
}
would have generated a compile time error due to the wrong pointer type. The code of your teacher "works", because the pointer to the first array in num is the same as the pointer to the first element of the first array in num, i. e. his code is equivalent to
int fun(int* arg);
int main() {
int num[3][3] = ...;
...
//both calls are equivalent
fun(num[0]);
fun(&num[0][0]);
}
which would compile without error.
This example shows a matrix, pointers to the first integers of arrays, and pointer to pointer
#include<stdio.h>
int fun(int (*p)[3]); /* p is pointer to array of 3 ints */
int main()
{
/* matrix */
int num[3][3]={{23,32,478},{55,0,56},{25,13, 80}};
/* three pointers to first integer of array */
int *pnum[3] = {num[0], num[1], num[2]};
/* pointer to pointer */
int **ppnum = pnum;
printf("%d\n", *(*(num+1)+2));
fun(num);
printf("%d\n", *(*(num+1)+2));
pnum[1][2] = 2;
printf("%d\n", *(*(num+1)+2));
ppnum[1][2] = 3;
printf("%d\n", *(*(num+1)+2));
return 0;
}
int fun(int (*p)[3])
{
p[1][2]=1;
return 0;
}
You do not actually need any pointers to print anything here.
Your int num[3][3] is actually an array of three elements, each of which is an array of three integers. Thus num[0][0] = 23, num[1][1] = 0, and so on. Thus you can say printf("%d", num[0][0]) to print the first element of the array.
Pointer to variable:
Pointer is variable which stores the address( of a variable). Every one know that.
Pointer to Array:
An array is a variable which has the starting point(address) of group of same objects.
And the pointer is a variable which stores the starting point(address) of an Array.
For example:
int iArray[3];
iArray is a variable which has an address value of three integers and the memory is allocated statically. And the below syntax is provided in a typical programming languages.
// iArray[0] = *(iArray+0);
// iArray[1] = *(iArray+1);
// iArray[2] = *(iArray+2);
In the above the iArray is a variable through which we can access the three integer variables, using any of the syntax mentioned above.
*(iArray+0); // Here iArray+0 is the address of the first object. and * is to dereference
*(iArray+1); // Here iArray+1 is the address of the second object. and * is to dereference
So simple, what is there to confuse.
The below lines are for your understanding
int iArray1[3];
int iArray2[3][3];
int *ipArray = 0;
ipArray = iArray1; // correct
ipArray = iArray2[0]; // correct
ipArray = iArray2[2]; // correct
int **ippArray = iArray2; // wrong
As per the above last line, compiler will not take it as a valid assignment. So **p is not used.
Pointer arthmatic cannot be applied on double arrays because of the way memory is allocated.

Resources