Reputation: 567
I missed my class today thanks to my car breaking down. Would array of pointers to type be something like the the following?
void *ary[10];
ary[0] = new int();
ary[1] = new float();
I'm still kinda fuzzy on what it is.
Upvotes: 1
Views: 301
Reputation: 6823
If this is C
code, there are a few things to point out. First off (as mentioned below), new
is not valid C
. It is valid in C++
, but you cannot allocate memory this way in C
. Instead, you will need to use malloc()
to allocate memory and free()
in lieu of C++'s delete
(these functions are included by #include <stdlib.h>
).
Now, in response to your comment. It seems like you are confused as to what a pointer actually is. A pointer is something which points to a location in memory. That is, a pointer is of some type on your system (i.e. maybe an unsigned long
) which ultimately holds some number. This number is the memory location of some data which you allocated (note that in practice due to virtual memory, these numbers do not correspond directly to the physical RAM addresses).
So in C
when you do something like below
char* x = (char*)malloc(sizeof(char));
You allocate a chunk of memory which for a single char
. The return value from malloc()
is a void*
which is why we casted it to char*
since that is what we want to use this memory as. This void*
is the location to the memory you requested (by calling malloc()
) which the operating system assigned to you for use. In order to actually use this memory, you need to dereference (i.e. the *
operator) the memory location. So after we have this memory allocated, we can try something like
*x = 'a';
Now the value at memory location x
is a
. In code, this can be denoted
if(*x == 'a')
printf("True");
It is important to note that sizeof(int*) == sizeof(char*)
even though sizeof(int) != sizeof(char)
. This is an important distinction. Notice how the first comparison compares sizes of pointer addresses and the second compares the size of the data structures (or, in this case, type primitives). The reason that this is important is that it enables your code above to actually work. Since all pointer addresses are of equal size, you can create an array of void*
and store any pointer type you wish in it without overwriting the buffer (i.e. each pointer nicely fits in array[i]
respectively). The power of void*
is that you can pass anything as a void*
(yes, you can technically cast anything to anything else, but this is convenient at times). The major loss of void*
, however, is that you cannot directly use it. That said, if I have code like this:
void passData(void* data)
{
char* x = (char*)data; // I _must_ do this to access the data
printf("%s\n", x);
}
int main()
{
char* x = (char*)malloc(10*sizeof(char));
*x = "test";
passData((void*)test);
free(x);
return 0;
}
I have to know my data type to use the void*
(or you must use metadata or similar to know how to handle this).
Now that we have some basis on memory allocation and what pointers actually do, I will address your comment. Since pointers simply point to memory addresses, if you have two pointers which point to the same memory address, then you simply have to ways of accessing the same data. For instance, consider the snippet below
#include <stdio.h>
int main()
{
int x = 0; // Stack variable
int* xPtr = &x; // & is the reference operator - it gives you the memory location of an object
x = 5;
printf("%d == %d\n", x, *xPtr); // xPtr == 5 since it points to the same memory location as x
*xPtr = 10;
printf("%d == %d\n", x, *xPtr); // x == 10 since we changed the value at the memory location of xPtr which is the same memory location which x is located at
return 0;
}
If you are not yet too familiar with the concept of pointers, this example below may be slightly clearer since it deals purely with heap memory:
#include <stdio.h>
int main()
{
int* xPtr = (int*)malloc(sizeof(int));
int* yPtr = xPtr; // Point yPtr to the same address as xPtr
*xPtr = 10; // The value of xPtr == 10 and so does the value of yPtr since they point to the same place
*yPtr = 12; // In a similar way, we modified the value again for both pointers.
yPtr = NULL; // Unset the memory location of yPtr - now yPtr no longer points to the same memory location as xPtr.
// In fact, now yPtr == NULL, so do _NOT_ try to dereference it or you will crash. In any event, the values of the pointers are now independent
*xPtr = 15; // Memory at the location xPtr points to has changed to 15. But yPtr no longer points to that location, so the value at the location yPtr points to has not changed.
yPtr = xPtr; // Change the memory location of yPtr to point to xPtr. Now yPtr's value is exactly the same as xPtr's value.
free(xPtr); // Only free ONE of the items pointing to the same memory location (otherwise you will double free)
return 0;
}
As you can see, you are simply accessing data in particular locations in memory. The pointer just points to that location in memory. Moving pointers around and making them point to different locations is known as pointer manipulation
. So that is why you can change memory at one location and it changes the value for any other pointer which points to that memory location.
Original Response (Question originally tagged C++
)
In reality, what you have done is more C-style
. This is technically valid (as long as you cast), but to do anything with these types later, you would have to know exactly what type is in what position and cast it back appropriately.
In the example you have given, you created an array which can hold void
pointers. That is, void*
is pretty much any "vanilla" type (since you can technically cast to anything but if you do not access the memory appropriately you are sure to crash). But you cannot dereference or do any real work on a void*
so you need to know what the memory actually is in order to cast it back. In any event, it is good to note that in C++
it is considered good practice to not use ()
for default/empty constructors - so simply new float;
will do fine.
The reason you can do this without messing anything up (i.e. different data structures have different sizes) is because pointers are simply ptr_t
types (on many machines maybe an unsigned long
or similar). So, realistically, the pointer just points to some location in memory, but all pointers (i.e. the addresses) are of equal size even if the objects the point to are different sizes.
In C++
it is better to use polymorphism to do this. For instance, create an array of "Ball" pointers which all are (at least with a base class of) of the class Ball
. Then, you can make them more specific. For instance, you could have a baseball, basketball, etc.
I am not entirely sure what you are trying without proper context, but this should look something like this
#include <isotream>
using namespace std;
class Ball
{
public:
virtual void ballType() const = 0;
};
class Basketball : public Ball
{
public:
virtual void ballType() const {
cout << "Basketball" << endl;
}
};
class Baseball : public Ball
{
public:
virtual void ballType() const {
cout << "Baseball" << endl;
}
};
Then, in general, if you use this as follows:
Ball* x[10];
x[0] = new Basketball;
x[1] = new Baseball;
x[0]->ballType();
x[1]->ballType();
delete x[0];
delete x[1];
This would print "Basketball" followed by "Baseball." If you could provide some more context as to what you are looking to do, I could tailor this response a little better to target your question.
Upvotes: 5
Reputation: 141
the pointer is an "integer" number it can point to anything you want in memory, if you have void *array it says that you have a void pointer called array, now depends how you use it you can have it type casted to int or other things and objects.
if you use void *array[10] that creates an array of pointers, now how you use the pointers its up to you. You can create objects or assign them to what ever data type you want,but this is not type safe since it`s a void pointer without type specification. it also requires strong type casting for usage with data types.
Technically you can have every pointer with different data type inside that array.
Upvotes: 1