I have come across a piece of example code that uses pointers and a simple subtraction to calculate the number of items in an array using C .
I have run the code and it works but when I do the math on paper I get a different answer.
There explanation does not really show why this works and I was hoping someone could explain this too me.
#include <iostream> using namespace std; int main() { int array[10] = {0, 9, 1, 8, 2, 7, 3, 6, 4, 5}; int stretch = *(&array 1) - array; cout << "Array is consists of: " << stretch << " numbers" << endl; cout << "Hence, Length of Array is: " << stretch; return 0; }
From: https://www.educba.com/c-plus-plus-length-of-array/
When I run the code I get the number 10.
When I print the results of *(&array 1)
and array
by
cout << *(&array 1) << endl; cout << array << endl;
I get of course two hex address's.
When I subtract these hex numbers I get 1C
or 28
???
Is it possible that C does not actually give the hex results or their translation to decimal but rather sees these numbers as addresses and therefore only returns the number of address slots remaining?
That is the closest I can come to an explanation if some one with more knowledge than I could explain this I would be very grateful.
CodePudding user response:
Let's take one step back and take it step-by-step to see if it will help. Continuing from my comment, the problem you are having difficulty with is one of type.
Let's take the array iteself:
int array[10] = {0, 9, 1, 8, 2, 7, 3, 6, 4, 5};
On access, an array is converted to a pointer to the first element in the array (e.g. the address of the first element) subject to caveats not relevant here. So when you say array
, you have type int *
, a pointer to the first element in array
.
Now what happens when I take the address of the array? (&array
in)
int stretch = *(&array 1) - array;
When you take the address of the array, the result is the same address as array
, but has type int (*)[10]
(a pointer-to-array-of int[10]
). When you add 1
to that pointer (recall type controls pointer arithmetic), you get the address for the pointer to the next array of int[10]
in memory after array
-- which will be 10 int
after the first element of array
.
So *(&array 1)
gives you the address to the next array of int[10]
after array
, and then dereference is only needed for type compatibility. When you dereference an int (*)[10]
you are left with int[10]
-- which on access gives you the address of the first element of that array (one after the original)
Think through the types and let me know if you have further questions.
CodePudding user response:
You forgot a small detail of how pointer addition or subtraction works. Let's start with a simple example.
int *p;
This is pointing to some integer. If, with your C compiler, int
s are four bytes long:
p;
This does not increment the actual pointer value by 1, but by 4. The pointer is now pointing to the next int
. If you look at the actual pointer value, in hexadecimal, it will increase by 4, not 1.
Pointer subtraction works the same way:
int *a;
int *b;
// ...
size_t c=b-a;
If the difference in the hexadecimal values of a
and b
is 12, the result of this subtraction will not be 12, but 3.
When I subtract these hex numbers I get 1C or 28 ???
There must've been a mistake with your subtraction. Your result should be 0x28
, or 40
(most likely you asked your debugger or compiler to do the subtraction, you got the result in hexadecimal and assumed that it was decimal instead). That would be the ten int
s you were looking for.
CodePudding user response:
I will try it with 5 items
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int array[] {1,2,3,4,5};
int items= sizeof(array)/sizeof(array[0]);
cout << items << endl;
int items2 = *(&array 1) - array;
cout << items2 << endl;
cout << array << endl;
cout << *(&array 1) << endl;
return 0;
}
root@localhost:~/Source/c # g arraySize.cpp
root@localhost:~/Source/c # ./a.out
5
5
0x7fe2ec2800
0x7fe2ec2814
using https://www.gigacalculator.com/calculators/hexadecimal-calculator.php to subtract the numbers from each other
I get
14 hex
20 decimal.
that fits with the 4 bytes to an integer.
thanx guys :)