I was searching how to create an array of pointers and copy it to CUDA memory. I found this post CUDA Double pointer memory copy but the following line in the accepted answer
int ** devicePointersStoredInDeviceMemory;
cudaMalloc( (void**)&devicePointersStoredInDeviceMemory, sizeof(int*)*N);
is bugging me a bit.
What's the meaning of passing the address of a double pointer and cast it to a void**?
Wouldn't &devicePointerStoredInDeviceMemory be the same as int*** so why cast it to void** instead of void***?
It works, but I do not understand why.
What's the meaning of passing the address of a double pointer and cast it to a void**? Wouldn't &devicePointerStoredInDeviceMemory be the same as int*** so why cast it to void** instead of void***?
The cudaMalloc function takes a void ** as its first parameter, so if we're going to call cudaMalloc, that's the type we need. The purpose of the first parameter is to tell codaMalloc where to store the pointer to the memory we allocated.
You could do this just as well:
void *j;
cudaMalloc(&j, sizeof(int*)*N); // stores result in j
int **devicePointersStoredInDeviceMemory = (int **) j;
Related
Hello im confused by typecasting pointers.
I understand that void can hold any type.
So if i have an int * with a value inside of it then i make a void * to the int * can i then typecast it to a char?
It's quite hard to explain what i mean and the title might be wrong but will this work?
And is it safe to do this. I've seen it used quite alot in C. Is this bad practise.
int main() {
int* a = new int{ 65 };
void* v = static_cast<int*>(a);
std::cout << *(static_cast<char *>(v));
}
I understand that void can hold any type.
You understand it wrong. Pointer does not hold data, it points to it. So integer pointer points to memory with holds integer, float pointer points where float is etc. Void pointer just points to some memory, but it says - I do not know what kind of data is there.
Now conversion. Technically you can convert almost any pointer to any (there are exceptions like function pointers or pointers to a member, but they are completely different beasts and it is not what you are asking about) as they all just pointers. But problem happens when you try to access memory where they point to. So if you have int in memory and try to read it as float or vice versa - that's illegal. Now therte is one exception - you can access any data through pointer to char (or unsigned char) as char represents byte. Void pointer is irrelevant here, you can convert from pointer of one type to another without void * involved:
int main() {
int* a = new int{ 65 };
unsigned char *uptr = reinterpret_cast<unsigned char *>( a );
for( size_t i = 0; i < sizeof(int); ++i )
std::cout << static_cast<unsigned int>( uptr[i] ) << ' ';
}
Live example
Note I casted uptr[i] to unsigned int, that is to print bytes as numbers, as C++ stream ( std::cout in this case) will print character as symbol, which would be meaningless in this case.
First any object pointer can be cast to void*. That's the generic "could be anything" solution inherited from C and you should not use it. The C++ way is to use template<typename T> and T* for such cases where you need an anything pointer.
Secondly any object pointer can also be cast to char * as a special case. Casting to char* gives you access to the memory representation of the object. It does not convert the object to a char or anything, you get access to the raw bits for the value stored in the object.
So the reason why casting to void* and then to char* works is that casting any object pointer to char* is valid. The intermediate step to void* is not needed at all.
This only works for char* or unsigned char* or any other variant of char pointer, including std::byte*. You can not static_cast an int* to float* for example and using a void* and intermediate step will not make that work either.
Note: The value printed by the code is implementation defined since the memory representation of an int and a char is defined by the implementation. Specifically their endianness and size of an int and the signedness of char. Apart from that it perfectly valid code.
The question though is: Why do you want to do this?
char* pointer = new char [5];
strcpy_s(pointer,4, "foo");
I am not fully understanding how pointers work. In my understanding the variable pointer is supposed to store the starting address of the new allocated string of chars. If so why is it important that the pointer is a char since its only storing an address.
why can't i just type
void* pointer = new char [5]
Thanks.
the pointer needs to know the size of its element, thanks to it you can use [] operator to reach a certain element of the array, how else would it know how much memory it has to move to get to the n-th element? If you could declare a pointer to any type as void, then it would have to automatically deduce the type it points to. Consider this piece of code:
char* pointer = new char[5];
pointer[3] = 'a';
for void* this would not be possible. I suppose that the strcpy_s function expects the first parameter as char*, not void* and that is the reason why your code doesn't compile. Pointer itself just allows you to know where some variable/array or even function is in memory, but when you specify pointer's type it gives it more flexibility.
I am wondering one thing, I am trying to remember c++ after long working with c# :)
And one thing bugs me, and I don't know why it is happening.
Pointer should be thing, which points somewhere to memory(it's address)
And pointer of pointer is address of the pointer. Simple, right? :D
Let's take a look at this code:
#include <iostream>
int main()
{
int* TestMas = new int[10]
{
1,2,3,4,5,6,7,8,9
};
for (size_t i = 0; i < 10; i++)
{
printf("%d\t", *(TestMas+i));
}
}
For some reason, values are printed out instead of the addresses, it should be *(TestMas+i) should be address of the array pointer, but how values are printed out, and not address?
If I try to use & to dereference the pointer, I get an error xD How is it working?
TestMas is a int *, or the address of an integer. When you assign it to new int[10], you're pointing it to the first of 10 contiguous integers in memory that you guarantee belong to you.
So when you do *(TestMas + i), you're doing pointer arithmetic, and then dereferencing the new pointer. Note that the syntactic sugar for exactly this operation would be TestMas[i].
You probably meant to leave off the dereference if you just wanted the address. So just:
std::cout << TestMas + i;
TestMas is a pointer to an int, not a pointer to a pointer. Its type is int *. A pointer to a pointer to an int would be int **
TestMas + i is also a pointer to an int, pointing to the i-th element of the array. *(TestMas + i) is calling the indirection operator on that pointer, which returns the object or function pointed-to by the pointer operand, not the address.
The address is the value of (TestMas+i) itself.
You can print it with:
printf("%p\t", (TestMas+i) );
I am learning c pointer and I follow c4learn as tutorial. In pointer to array of string section, which has following code:
char *arr[4] = {"C","C++","Java","VBA"};
char *(*ptr)[4] = &arr;
I didn't get what is
*(*ptr)[4]
? Wasn't it possible to use it like
**ptr
instead?
Update1:
Currently I am in the next section, function pointer and I saw again similar code:
void *(*ptr)();
char *(*ptr)[4]
is a pointer to a length 4 array of pointers to char (char*). Since arr is a length 4 array of char*, ptr can be made to point to arr by assigning it the address of arr, &arr.
void *(*ptr)();
Is a pointer to a parameterless function returning void*. For example
void* fun(); // function
void *(*ptr)(); // function pointer
p = fun; // function pointer points to function
C syntax can be quite confusing, so it may be easier to illustrate this with some examples. Note that whitespaces between T and ; make no difference.
T name[N]; // size N array of T
T * name[N]; // size N array of pointer to T
T (*name)[N]; // pointer to size N array of T
T ** name[N]; // size N array of pointer to pointer to T
T *(*name)[N]; // pointer to size N array of pointer to T
char *ar[4];
Declares ar as an array of four pointers to chars.
To declare a pointer, you take the declaration of something it can point to, and replace the variable name with (*some_other_name).
So char *(*ptr)[4]; declares ptr as a pointer to an array of four pointers to chars. Normally you can drop the brackets, but in this case, char **ptr[4]; would declare ptr as an array of four pointers to pointers to chars which is not what we want.
Similarly for a function pointer. void *fn() declares a function. void *(*ptr)() declares a pointer that could point to fn. void **ptr() would declare a function with a different return type.
Wasn't it possible to use it like **ptr instead?
Yes, assuming you mean like ptr2 below:
const char* arr[4] = {"C","C++","Java","VBA"};
const char* (*ptr)[4] = &arr;
const char** ptr2 = arr;
There is a difference though... with ptr the type still encodes the array length, so you can pass ptr but not ptr2 to functions like the one below:
template <size_t N>
void f(const char* (&arr)[N]) { ...can use N in implementation... }
Currently I am in the next section, function pointer and I saw again similar code: void *(*ptr)();
That creates a pointer to a function - taking no arguments - returning a void* (i.e. the address of an unspecified type of data, or nullptr).
char *(*ptr)[4] is an array pointer to an array of pointers.
With less obfuscated syntax: if you have a plain array int arr[4]; then you can have an array pointer to such an array by declaring int (*arr_ptr)[4].
So there are arrays, regular pointers and array pointers. Things get confusing because when you use the array name by itself, arr, it decays into a regular pointer to the first element. Similarly, if you have a regular pointer and let it point at the array, ptr = arr; it actually just points at the first element of the array.
Array pointers on the other hand, points at the "whole array". If you take sizeof(*arr_ptr) from the example above, you would get 4*sizeof(int), 4*4=16 bytes on a 32-bit machine.
It should be noted that an array pointer a mildly useful thing to have. If you are a beginner, you don't really need to waste your time trying to understand what this is. Array pointers are mainly there for language consistency reasons. The only real practical use for array pointers is pointer arithmetic on arrays-of-arrays, and dynamic allocation of multi-dimensional arrays.
for example in this code:
double **Data, *DataT;
Data = (double **)malloc(3*sizeof(double *)+3*12*sizeof(double));
I just read that malloc allocates memory from the heap. But i could not find what that (double **) meant in front of the malloc.
There is a line of code directly after this as well that i have seen this in.
for (i = 0, DataT = (double *)(Data+3); i < 3; i++, DataT += 12)
Here there is a (double *) in front of Data+3
Could you please explain to me what that does?
Thank you
malloc() returns type void *, while your pointer is of type double * or double **. The operator before malloc - looking like (type) - is the type conversion operator, needed to convert malloc's return value to the type of the pointer you are using.
(double**) is a cast. it says that the result of the malloc is changed to double**.
malloc returns void* according to the standard.
so it is casted to double** to be the same nature of data : double**.
but in C, there is no need to the cat because void * is casted implicitly. so you can write directly :
Data = malloc(3*sizeof(double *)+3*12*sizeof(double));
as your question is for C++, which is compatible with C malloc, you have to put the cast : (double**).
so you can use malloc and the cast if you have a code that you want to use in programs in C and in C++. else, use new and delete...
It's a type cast. The rules for its syntax and usage should be a part of any C primer. The definitive book for this kind of thing is the one by Kernighan and Ritchie.
It means "pointer to a pointer".
The (double **) is a casting operator. It casts the void pointer returned by malloc to a pointer to pointer to double.
It's a pointer to a pointer. e.g. a double dereference.
c -> some memory address
*c -> whatever is at the memory address stored in c
**c -> whatever is at the memory address stored in *c
The (double**) and (double*) are what are known as C style casts. These make whatever type is after them into the type inside the parentheses.
The first C style cast is turning the return type of malloc into double** so it can be stored in the double** variable.
The second cast is turning it into a double*, so it can be dereferenced correctly.
double** means that you're allocating a pointer to a pointer of a double