So I'm trying to learn some C with pointers but I'm having trouble understanding the following code snippet. first and last are the first and last item. So you have something like first, middle, last. but what is last - 1? Is it just the second last element? so if we have some thing first, last with no middle then this would be true?
item *first, item *last
if (first == last -1)
return 0
CodePudding user response:
To expound on @John Bode's answer, a pointer is just a number. It's an address in memory. Arrays are laid out contiguously in memory. The first element has the lowest address, and the last element the highest address.
So, if we have the address for the first element in the array, and we add 1, we get the memory address of the next element in the array. Your compiler should know how many bytes each element in the array takes up unless you're doing weird casting on the pointers. Knowing this, the program adds that many bytes to the address.
So, to get to the next address, we simply add 1. To get to the previous address, we can subtract 1.
CodePudding user response:
Imagine you have an array of item
:
item arr[10];
and then you set first
and last
to point to the first and last items of the array, respectively:
item *first = &arr[0];
item *last = &arr[9];
which gives us something like
item item *
---
arr: | | arr[0] <---- first
---
| | arr[1]
---
| | arr[2]
---
...
---
| | arr[8] <---- last - 1
---
| | arr[9] <---- last
---
The expression last - 1
gives you a pointer to the object immediately before the object pointed to by last
, assuming both objects are members of the same array, or that last
points to an object immediately following the end of the array.
C doesn't guarantee that individual variables are laid out in any specific order, so adding or subtracting an offset to a pointer only works (that is, gives you a useful result) if you're pointing to an element of an array. IOW, if you had something like
item a;
item b;
item *first = &a;
item *last = &b;
then the expression last - 1
isn't guaranteed to point to a
(nor is first 1
guaranteed to point to b
).
CodePudding user response:
Yet another pointer math illustration
Not knowing the type of item
in your example code, I will choose to make it a struct:
typedef struct {
int a;
int b;
float c;
} item_s;//new type
Using the new type item_s
, create the following array and a set of pointers to illustrate pointer arithmetic
item_s item[5] = {{1,2,3.0},{10,20,30.0},{15,25,35.0},{16,26,36.0},{17,27,37.0}};
item_s *first, *last, *index;
//set the `first` and `last` pointers to the first and last element of the array
first = &item[0];
last = &item[4];
//now illustrate type of pointer manipulation and its results
index = first 1 ;// index now points to the area of memory occupied by item[1]
// first 1*sizeof(item_s)
printf("a: %d\nb: %d\nc:%f\n", index->a, index->b, index->c);
index = last - 1;//index points to the area of memory occupied by item[3]
// last - 1*sizeof(item_s)
printf("a: %d\nb: %d\nc:%f\n", index->a, index->b, index->c);
index = last 1;//index points to an un-owned area of memory and possibly a seg-fault.
//printf("a: %d\nb: %d\nc:%f\n", index->a, index->b, index->c);//UB
So when you increment a pointer by 1
, the new memory location pointed to is exactly the
old memory location 1 *
sizeof(pointer type)
If you increment it by 3, then it is
old memory location 3 *
sizeof(pointer type)