This question already has answers here:
When a function has a specific-size array parameter, why is it replaced with a pointer?
(3 answers)
Closed 5 years ago.
I was looking at this code and understood pretty much all of it except one thing:
what does Arr1++ means?
What does it do to the array? since Arr1 is not just a normal variable like int..
bool theSameElements(int Arr1[], int Arr2[], int size)
{
int temp;
if (size == 0)
{
return true;
}
for (int i = 0; i < size; i++)
{
if (Arr1[0] == Arr2[i])
{
temp = Arr2[i];
Arr2[i] = Arr2[0];
Arr2[0] = temp;
Arr1++;
Arr2++;
return theSameElements(Arr1, Arr2, size - 1);
}
}
return false;
}
Any array passed as function parameter is implicitly converted / decays to a pointer of type int*. Now the Arr1 is a pointer pointing to the first array element namely Arr1[0]. This is known as the Array-to-pointer decay. Applying the post-increment operator:
Arr1++;
increments the pointer value by the size of the data it points to so now it points to the second array element Arr1[1].
That being said you should prefer std::array to raw arrays and smart pointers to raw pointers.
So what you need to know is that Arr, in this case, is the pointer to the array. So when you do Arr++ you are basically incrementing the pointer to this array.
Function parameters which appear to have array type, in fact have pointer type. int foo[3] and int foo[], in the context of a function parameter list (and only in that context), are exactly the same as int* foo. Because of this, you can do things to them that you wouldn't ordinarily be able to do to arrays, such as reassign their values.
Related
My code:
.h file:
extern const int* g_position;
inline DWORD pos_x(BYTE v) {
if (1 <= v && v <= 3)
return g_position[v][0];
return 0;
}
inline DWORD pos_y(BYTE v) {
if (1 <= v && v <= 3)
return g_position[v][1];
return 0;
}
.cpp file:
const int* g_position = (int*) 0x86b2fdc;
What I am trying to do is address the function which is basically a two-dimensional array:
(DWORD (*)[4][2]) 0x86b2fdc<g_position>
For some reason I am getting the following error(s) while compiling:
In function 'gev::DWORD pos_y(BYTE)':
error: invalid types 'const int[int]' for array subscript
return g_position[v][0];
What is wrong in my code? I am declaring the g_position as an array type so it should work.
g_position is declared as int*, which allows only one level of dereferencing, but you are trying to perform two dereferences instead. You need to change the declaration to int** instead:
extern const int** g_position;
const int** g_position = (int**) 0x86b2fdc;
Update:
An int** is not quite the same thing as an int[][]. However, if you take into account that an int[4][2] has the same memory layout as an int[8], and you can access the content of an int[] using an int*, then try this instead:
extern const int* g_position;
inline DWORD pos_x(BYTE v)
{
if (1 <= v && v <= 3)
return g_position[(v*4)+0];
return 0;
}
inline DWORD pos_y(BYTE v)
{
if (1 <= v && v <= 3)
return g_position[(v*4)+1];
return 0;
}
const int* g_position = (int*) 0x86b2fdc;
Is 0x86b2fdc the address of an array of arrays? Or the address of an array of pointers to arrays? Or is it the address of a pointer to something?
Assuming it is the address of an array of arrays of 4 ints, you can just declare g_position as a pointer to such:
extern const int (*g_position)[4]; /* pointer to arrays of 4 ints */
in the .cpp file:
const int (*g_position)[4] = (int (*)[4])0x86b2fdc;
Your basic confusion seems to be confusing pointers and arrays, which are not the same thing:
an array is a sequence of objects laid out one after the other in memory. You can't do anything with an array other than initialize it, get its size, and get a pointer to it or its 0th element
a pointer is an address that refers to memory. The memory pointed at may contain a single object of the appropriate type, or it may contain an array (in which case the pointer points at the 0th element of the array.
Whenever you refer to an array (except when using sizeof or unary &), the compiler silently gives you a pointer to the 0th element of the array, so the name of such a pointer is mostly interchangeable with the name of the array. Your pos_ functions don't use sizeof or & on g_position, so for your purposes, they are interchangeable. you just need to get the type correct.
This question already has answers here:
When a function has a specific-size array parameter, why is it replaced with a pointer?
(3 answers)
Closed 8 years ago.
I have the following function in C
int func(char* param1[], int param2[])
{
//Want to calculate size of param1 array
}
I tried
n = sizeof(param1)/sizeof(char*);
but this doesnt give me the correct answer.
Note that the function prototype
int func(char* param1[], int param2[]);
is equivalent to
int func(char **param1, int *param2);
This means the function parameters param1 and param2 are pointers, not arrays. Pointers and arrays are different types.
sizeof(param1) / sizeof(char*);
// equivalent to
sizeof(char **) / sizeof(char *) // always 1
The above expression always evaluates to 1 because size of all pointer types is the same (except for a function pointer on which sizeof operator may not be applied).
That's because you cannot pass an array to a function. What's actually gets passed is a pointer to the first element of the array. The pointer has no size information of the array passed to the function. Therefore, you must explicitly pass the array lengths to your function. It should have the prototype
int func(char *param1[], int param2[], int len_param1, int len_param2);
There are two ways of doing this:
Simplest and most obvious, pass the length in the function argument
Have a NULL at the end of the array (NULL-terminator):
char arr[] = { "what", "so", "ever", NULL }; Then loop:
int i;
for (i = 0; arr[i] != NULL; i++)
...
However, if you're passing an array like the example above to that function (a static one), just pass the length as an argument by using same logic...
func(arr, sizeof(arr) / sizeof(arr[0]);
C isn't smart enough to know the size of an array at runtime. It can only tell you the size of a data type, which is determined at compile-time.
The solution to this is to add a size parameter to the function, like this:
int func(char* param1[], int param2[], int n)
or to use a null-terminated array, so that you can use a loop to iterate through the array:
int func(char* param1[], int param2[]){
int size;
for(size = 0; param1[size] != NULL; size++);
...
The point is, an array in C is just a block of memory that you can happen to treat as a bunch of variables next to each other. There's no built-in way to figure out how many variables are in the block, since there's no built-in way to mark the beginning or end of the block.
char* param1[]
will make param a pointer of type char ** so the result of
n = sizeof(param1)/sizeof(char*);
is sizeof pointer by size of pointer i.e. 1. and its not size of array
This question already has answers here:
If an array name is treated as a pointer, why do I get a compile time error of Lvalue required when incrementing an array?
(3 answers)
Closed 9 years ago.
int main()
{
int a[]={2,3,4,5,6};
int j;
for(j=0;j<5;j++)
{
printf("%d\n",*a);
a++;
}
return;
}
gives Lvalue required error
but
int main()
{
int a[]={2,3,4,5,6};
int *p,j;
p=a;
for(j=0;j<5;j++)
{
printf("%d\n",*p);
p++;
}
return;
}
doesn't.
why????
So I dont understant that even though in a[], a is treated as a pointer so why cant we increment it just like a pointer
Because array name is not a separate memory cell. It is a named memory extent. So it is not clear where to store the incremented value.
Pointers and arrays are not completely interchangeable.
int main ()
{
int var[MAX] = {10, 100, 200};
for (int i = 0; i < MAX; i++)
{
*var = i; // This is a correct syntax
var++; // This is incorrect.
}
return 0;
}
It is perfectly acceptable to apply the pointer operator * to var but it is illegal to modify var value. The reason for this is that var is a constant that points to the beginning of an array and can not be used as l-value.
Because an array name generates a pointer constant, it can still be used in pointer-style expressions, as long as it is not modified
This question already has answers here:
What is array to pointer decay?
(11 answers)
How is this C++ code working
(1 answer)
Closed 9 years ago.
At first I would guess that the values of k1 won't be in the main space. But then I realized that an array is a pointer, so is there any difference? I think that is the same, but maybe anyone can find some other technical differences. Maybe is faster passing a pointer?
#include <iostream>
using namespace std;
void g(double [],int );
void f(double* [],int );
int main()
{
int n = 10;
double *k1, *k2;
k1 = new double[n];
k2 = new double[n];
g(k1,n);
f(&k2,n);
for(int i = 0;i <n;i++)
{
cout << k1[i]<< " ";
cout << k2[i] << endl;
}
delete [] k1;
delete [] k2;
return 0;
}
void g(double h[],int n)
{
for(int i = 0;i <n;i++)
h[i]=i;
}
void f(double* h[],int n)
{
for(int i = 0;i <n;i++)
(*h)[i]=i;
}
First of all, arrays are not pointers. This is an array of 10 doubles:
double a[10];
This is a pointer to double:
double *p;
This is a pointer to an array of 10 doubles:
double (*pa)[10];
And this is an array of pointers to doubles:
double *pa[10];
Arrays and pointers are only the same when declared as function arguments. But arrays can be converted (decay) into pointers to the first elemento of the array:
double a[10];
double *p = a;
double *q = &a[0]; //same as p
In your sample code:
double *x = new double[10];
You are creating a dynamic array of 10 doubles and getting a pointer to the first element of that array. You could also create a new array and get a pointer-to-array:
double (*x)[10] = new double (*)[10];
But this show of weird syntax is seldom useful.
About functions, this is a function taking an array of doubles:
void g1(double h[], int n);
And this is a function taking a pointer to an array of 10 doubles:
void g2(double (*h)[10]);
In the pointer-to-array case you need to specify the size of the array, because you cannot create a pointer to an unknown-size array.
That's why arrays are actually passed to functions as pointers. But pointers to the first member of the array, not pointers to the array itself. So the first function is actually identical to this one:
void g1(double *h, int n);
Since you only pass the pointer to the first member of the array (pointer to double) you need also to specify the size of the array, in an additional paramenter. The advantage is that you can pass arrays of any size. And even splices of an array:
double x[20];
g1(x + 10, 5); //pass x[10..15]
About which one is faster, they are both the same, they are actually pointers to the same memory address. Note that arrays are only passed by copy if they are part of a struct, and the struct is passed by value.
My recommendation is: if you use C stick to the idiomatic C, use pointers to the first member of the array when necessary, and avoid the pointer-to-array syntax when possible. If you use C++ use containers, iterators and ranges.
void f(double* h[],int n)
is not accepting a pointer to an array. You've declared it to accept an array of pointers.
The only reason it works is that function parameters declared as arrays are silently turned into pointers, and so it is equivalent to:
void f(double** h,int n)
which is what you wanted after all.
This (rejected by g++) code would use a pointer to an array:
void f(double (*h)[],int n)
With this declaration:
void f(double* [],int );
You are saying that, as first parameter, you are taking an array of pointers to double.
When you dereference that parameter (which is treated like a pointer to pointer) with (*h), you actually get the address of the first location of the array.
Even though you passed the pointer by-value, the memory that it is pointing to can still be changed by a function.
void g(double h[],int n);
In that function you are technically passing a pointer.
void f(double* h[],int n);
However in this one, you are passing a pointer to an array, which resolves to a pointer to pointer as it is a function parameter*.
*Credit to Ben Voigt
Many programmers have a mental model of how the compiler works that includes "an array is just a pointer". This model is incorrect.
typedef int[10] Array;
typedef Array * PointerToArray;
typedef int * Pointer;
Array a = {0,1,2,3,4,5,6,7,8,9};
PointerToArray pa;
Pointer pint = a; // the compiler casts this automatically to a different type.
At this point pint and pa have the same binary value, but pa[1] and a[1] do NOT reference the same location in memory. It is important to understand why.
This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 4 years ago.
I'm having trouble finding the length of an pointer array. Let's say I have:
char array[40] = "hello"; // size 40
int length = sizeof array / sizeof array[0]; // no problem returns 40
//How do I get the length of the array with only a pointer to the first element in that array?
char* pchar = array;
//if
std::strlen(pchar); // this returns the length of 5... i want length 40
//if
int count = 0;
while(true)
{
if(*(pchar + count) == '\0') // returns 5...
break;
count++;
}
How do I get it to return length 40 just from a pointer to the first element in the array?
I found that I can do this.
int count = 0;
while(true)
{
if(*(pchar + count) == '\0' && *(pchar + count + 1) != '\0')
break;
count++;
}
This returns 39, this is good but I feel like this can be buggy in some situations.
You can't, I'm afraid. You need to pass the length of the array to anyone who needs it. Or you can use a std::array or std::vector or similar, which keep track of the length themselves.
You can't. And the moral is, don't use pointers and arrays, use vectors. You can always get the size of a vector.
C++ has proper string type:
std::string
which you may find helpful here. Even if you're passing it to function that accepts const char*, it has .c_str() method that allows you to pass it to function that accept a pointer. If the other function needs to modify the string, you can use &str[0] which is valid for many implementations of C++, and is required to work for C++11. Just make sure you resize() them to the correct size.
Some of the other containers in C++ are:
std::array (C++11) Array of constant size. Better than plain old C array, as it has size() method.
std::vector Dynamic array (Java ArrayList equivalent)
As for your question - there is no way to find size of a pointed array. How could you even do that? It's just a stupid pointer.
It is true that you cannot get the array size from a pointer to an element of the array.
If the reason you only have a pointer is because you are implementing a function that takes an array parameter as an argument like this:
void foo (T *p) {
// p is a pointer to T
}
then you can use a template function instead to get the array size to the function.
template <unsigned N, typename T>
void foo (T (&p)[N]) {
// p is a reference to an array[N] of T
std::cout << "array has " << N << " elements" << std::endl;
std::cout << "array has "
<< sizeof(p)/sizeof(p[0])
<< " elements"
<< std::endl;
}
int main ()
{
int array[40];
char array2[25];
foo(array);
foo(array2);
return 0;
}
If you want to keep simple and not use #include <array.h>, you can make a struct where you array sizes are. A little bit like:
struct
{
int* int_Array;
int array_Size;
}
That way, you can to whatever you want (like deleting your instances or something)