I create an array:
unsigned short* array = malloc(sizeof(unsigned short)*N);
Assign values to it:
for(i=0; i<N; i++){
array[i] = rand()%USHRT_MAX;
}
Cast it to a void* and pass it to a worker thread which will find the max value in the array:
pthread_create(&threads[0], NULL, findMax, (void*)&array);
Which looks like this:
void* findMax(void* arg){
int i = 0;
unsigned short max = 0;
unsigned short* table = (unsigned short*)arg;
for(i=0;i<N;i++){
if(table[i]> max){
max = table[i];
}
}
printf("Max: %d\n", max);
}
The issue is that the numbers assigned in the array are misformatted. For example with the N randomly generated numbers: 3664 50980 37495 12215 33721, this loop will interpret the numbers as following instead:
table[0] = 28680
table[1] = 2506
table[2] = 5
table[3] = 0
table[4] = 32736
With the 5 and 0 as recurring pattern on the 2nd and 3rd place in the array.
I'm clearly overstepping some memory boundries, what is happening here and how do I fix it?
Change:
(void*)&array
to this:
(void*)array
since void* findMax(void* arg) expects a pointer, and you were passing the address of the pointer.
A pointer variable is a variable declared with a derived type specifier.
It is still a variable and it still has an address.
The value on that address is an address of a variable of that type.
A "pointer type" usually refers to void* while short pointer to short* and so on. void pointers can point to any variable, but you will have to convert it to a pointer of a generic type, when using it, using type-casting,
therefore you only cast void* when you are converting it to something else.
So if you add ampersand (reference) operator to a pointer &ptr you are ultimately referencing to the address of the pointer variable. It can be useful if you want to "repoint" the pointer from within a function.
Your code can still succeed, but you will have to declare the arguments differently:
( foo(void** vp) )
And to access the variable it points to, you dereference the void**:
void* p = *vp;
Related
I'm trying to make a sort of container for multiple different structs. Unfortunately C only allows type specific arrays, meaning I'd have to make a different array for each type of struct.
The current solution I came up with is a container that holds memory addresses. This way the program can just pass the memory address of one of the elements to a function.
Currently the only code I have is a failed attempt using void pointers (not really familiar with pointers and memory addresses yet unfortunately)
The following is my test code I was writing to try and understand how this stuff works:
void* arr[10]={};
int len=0;
int n[5]={1,2,3,4,5};
for (int i=0;i<5;i++) { //add pointers nums in n to arr
arr[i]=(void*)(&n[i]);
len++;
}
for (int i=0;i<len;i++) { //print contents of arr
printf("%p\n", (void*)arr[i]);
printf("\t%d\n", arr[i]); //trying to print actual value (eg. 2 for index 2) but not really sure how to...
}
Thanks!
Your approach is correct but there is some stuff missing...
In C any object pointer can be converted to a void-pointer and back to a pointer of the original type. So an int-pointer can be converted to a void-pointer an back to an int-pointer. And a float-pointer can be converted to a void-pointer an back to an float-pointer.
So using an array of void-pointers to store pointers to different object types is a fine approach.
But... in order to convert the void-pointer back to the original type, you need to know what the original type was. If you just saves the void-pointer, you don't have that information.
Instead consider something like:
struct gp
{
void* p;
unsigned type_tag;
}
#define INT_TYPE 0
#define FLOAT_TYPE 1
and use it like:
struct gp arr[2];
int n = 42;
float f = 42.42;
arr[0].p = &n;
arr[0].type_tag = INT_TYPE;
arr[1].p = &f;
arr[1].type_tag = FLOAT_TYPE;
for (int i=0; i < 2; ++i)
{
if (arr[i].type_tag == INT_TYPE)
{
int* p = (int*)arr[i].p; // Cast void-pointer back to int-pointer
printf("%d\n", *p); // Get int-value using *p, i.e. dereference the pointer
}
else if (arr[i].type_tag == FLOAT_TYPE)
{
int* p = (float*)arr[i].p; // Cast void-pointer back to float-pointer
printf("%f\n", *p); // Get float-value using *p, i.e. dereference the pointer
}
}
You need to derefence the pointer stored in the array. You also need to cast it to the original type of the referenced objects.
printf("\t%d\n", *(int *)arr[i]);
I'm new in programming and learning about pointers in array. I'm a bit confused right now. Have a look at the program below:
#include <stdio.h>
int fun();
int main()
{
int num[3][3]={23,32,478,55,0,56,25,13, 80};
printf("%d\n",*(*(num+0)+1));
fun(num);
printf("%d\n", *(*(num+0)+1));
*(*(num+0)+0)=23;
printf("%d\n",*(*(num+0)));
return 0;
}
int fun(*p) // Compilation error
{
*(p+0)=0;
return 0;
}
This was the program written in my teacher's notes. Here in the main() function, in the printf() function dereference operator is being used two times because num is pointer to array so first time dereference operator will give pointer to int and then second one will give the value at which the pointer is pointing to.
My question is that when I'm passing the array name as argument to the function fun() then why *p is used; why not **p as num is a pointer to array?
Second thing why *(p+0) is used to change the value of zeroth element of the array; why not *(*(p+0)+0)=0 as in the main() function *(*(num+0)+0) is used to change the value of zeroth element?
The whole thing is very confusing for me but I have to understand it anyway. I have searched about this and found that there is a difference between pointer to array and pointer to pointer but I couldn't understand much.
The trick is the array-pointer-decay: When you mention the name of an array, it will decay into a pointer to its first element in almost all contexts. That is num is simply an array of three arrays of three integers (type = int [3][3]).
Lets analyse the expression *(*(num + 1) + 2).
When you mention num in the expression *(num + 1), it decays into a pointer to its first element which is an array of three integers (type = int (*)[3]). On this pointer pointer arithmetic is performed, and the size of whatever the pointer points to is added to the value of the pointer. In this case it is the size of an array of three integers (that's 12 bytes on many machines). After dereferencing the pointer, you are left with a type of int [3].
However, this dereferencing only concerns the type, because right after the dereferencing operation, we see expression *(/*expression of type int[3]*/ + 2), so the inner expression decays back into a pointer to the first array element. This pointer contains the same address as the pointer that results from num + 1, but it has a different type: int*. Consequently, the pointer arithmetic on this pointer advances the pointer by two integers (8 bytes). So the expression *(*(num + 1) + 2) yields the integer element at an offset of 12 + 8 = 20 bytes, which is the sixth integer in the array.
Regarding your question about the call of fun(), that call is actually broken, and only works because your teacher did not include the arguments in the forward declaration of fun(). The code
int fun(int* arg);
int main() {
int num[3][3] = ...;
...
fun(num);
}
would have generated a compile time error due to the wrong pointer type. The code of your teacher "works", because the pointer to the first array in num is the same as the pointer to the first element of the first array in num, i. e. his code is equivalent to
int fun(int* arg);
int main() {
int num[3][3] = ...;
...
//both calls are equivalent
fun(num[0]);
fun(&num[0][0]);
}
which would compile without error.
This example shows a matrix, pointers to the first integers of arrays, and pointer to pointer
#include<stdio.h>
int fun(int (*p)[3]); /* p is pointer to array of 3 ints */
int main()
{
/* matrix */
int num[3][3]={{23,32,478},{55,0,56},{25,13, 80}};
/* three pointers to first integer of array */
int *pnum[3] = {num[0], num[1], num[2]};
/* pointer to pointer */
int **ppnum = pnum;
printf("%d\n", *(*(num+1)+2));
fun(num);
printf("%d\n", *(*(num+1)+2));
pnum[1][2] = 2;
printf("%d\n", *(*(num+1)+2));
ppnum[1][2] = 3;
printf("%d\n", *(*(num+1)+2));
return 0;
}
int fun(int (*p)[3])
{
p[1][2]=1;
return 0;
}
You do not actually need any pointers to print anything here.
Your int num[3][3] is actually an array of three elements, each of which is an array of three integers. Thus num[0][0] = 23, num[1][1] = 0, and so on. Thus you can say printf("%d", num[0][0]) to print the first element of the array.
Pointer to variable:
Pointer is variable which stores the address( of a variable). Every one know that.
Pointer to Array:
An array is a variable which has the starting point(address) of group of same objects.
And the pointer is a variable which stores the starting point(address) of an Array.
For example:
int iArray[3];
iArray is a variable which has an address value of three integers and the memory is allocated statically. And the below syntax is provided in a typical programming languages.
// iArray[0] = *(iArray+0);
// iArray[1] = *(iArray+1);
// iArray[2] = *(iArray+2);
In the above the iArray is a variable through which we can access the three integer variables, using any of the syntax mentioned above.
*(iArray+0); // Here iArray+0 is the address of the first object. and * is to dereference
*(iArray+1); // Here iArray+1 is the address of the second object. and * is to dereference
So simple, what is there to confuse.
The below lines are for your understanding
int iArray1[3];
int iArray2[3][3];
int *ipArray = 0;
ipArray = iArray1; // correct
ipArray = iArray2[0]; // correct
ipArray = iArray2[2]; // correct
int **ippArray = iArray2; // wrong
As per the above last line, compiler will not take it as a valid assignment. So **p is not used.
Pointer arthmatic cannot be applied on double arrays because of the way memory is allocated.
I am trying to pass struct to thread. Unfortunatelty when it happens i can no longer use p[i][j]. I am getting error: subscripted value is neither array nor pointer nor vector
typedef struct MY_M {
int *p1;
int *p2;
} MY_M;
int *M1[r];
for (i=0; i<r; i++){
M1[i] = (int *)malloc(c * sizeof(int));}
pthread_t thread1;
struct MY_M *p = malloc(sizeof(struct MY_M));
p-> p1 = *M1;
p-> p1 = *M2;
int ret = pthread_create(&thread1,NULL,thread,(void*) p);
thread here:
void* thread(void* parameter )
{
MY_M **p = (MY_M*)parameter;
p->p1[0][0] = 5;
}
When i comment p[0][0] the program is working fine. Why it is not working? I would be grateful for any help.
I can't tell exactly what you are trying to accomplish here, but I can see a number of errors.
In the first place, you assign two values to p->p1. I assume this is probably a mistake and you meant to assign one value to p->p1 and another to p->p2. (And where did M2 come from?)
Second, int *M1[r]; will allocate r pointers to int on the stack, which means the array containing the buffers will become invalidated shortly after the function returns.
You are also dereferencing M1 during assignment, which means you are only pointing to the first buffer that you allocated. Again, I can't tell exactly what you are trying to do with that, so I don't know what to recommend.
p1 is also type int*, which means it contains the address of an int, so it can only be dereferenced once and will resolve to int. If you want to dereference it twice (p->p1[x][y]) it should be type int** or pointer to some other dereference-able type.
Also, you cast parameter to MY_M*, but then assign it to a variable of type MY_M**. That is not correct (in fact, isn't that giving you a compiler error?)
As far as I can tell, you are simply trying to allocate some structure that your thread will later have access to. If that is the case, the code would be something like this:
typedef struct MY_M {
int* p1;
int* p2;
} MY_M;
MY_M* p = (MY_M*)malloc( sizeof(MY_M) );
p->p1 = (int*)malloc( c * sizeof(int) );
p->p2 = (int*)malloc( c * sizeof(int) );
pthread_t thread1;
int ret = pthread_create(&thread1, NULL, thread, (void*)p);
thread here:
void* thread(void* parameter)
{
MY_M *p = (MY_M*)parameter;
p->p1[0] = 5;
}
Overall, it seems that you don't fully understand pointers properly. I can try to give a brief rundown, but do consult other guides and references to fully understand the concept.
First: a pointer is an address. So int* a = &b; means that a of type int* will contain b's address, and therefore it points to b. If you dereference a pointer, that means you take the address value that it holds and follow the address to its original source. So *a dereferences a, resolving to the value stored in b.
Array index syntax is equivalent to offset + dereferencing, so when you say p->p1[0][0], that is really equivalent to *((*(p->p1+0))+0), which dereferences the variable twice.
You can't dereference something that isn't a pointer (i.e., doesn't contain an address). That's why your int* can't be dereferenced twice. After dereferencing it once, it is now an int, which does not contain an address and cannot be dereferenced.
I hope this helps.
What you're actually using is an array of pointers (to arrays), rather than a proper 2D array -- though that isn't really a problem here. As for why it isn't working, you simply have the wrong type for p in your thread function -- it should be int ** rather than int *.
Pointer1 points to 5.
Pointer2 points to 3.
I want to multiply 5*3, but I only have the pointers. How would I do this in C?
Also, what does uint32_t *pointer mean when:
pointer[2] = {1, 2};
I do not know what is so hard for the answerers to understand about this question. It is obviously about dereferencing pointers.
This is how you display the contents of the pointer that it is pointing to:
#include <stdio.h>
int main(void)
{
int num1 = 5;
int num2 = 3;
int* num1_ptr = &num1;
int* num2_ptr - &num2;
int sum = *num1_ptr * *num2_ptr;
printf("%d\n", sum);
return 0;
}
*num1_ptr and *num2_ptr takes your pointers and references what the contents of that memory address.
I can't answer the first half of your question without more information, but uint32_t* pointer is simply a pointer to an unsigned 32-bit integer value (unsigned int and uint32_t are usually equivalent types, depending on your compiler).
If I see a declaration that simply reads uint32_t* pointer without more information I'm going to assume it's a pointer to a single value, and that using the indexing operator [n] on such a pointer is basically overflowing the single-element-sized buffer. However if the pointer is assigned the result from an array or buffer function (e.g. malloc, calloc, etc) then using the indexing operator is fine, however I would prefer to see uint32_t pointer[] used as the declaration as it makes it much easier to determine the developer's intent.
uint32_t *pointer is just a pointer with garbage value unless you point it to something.
pointer[0] = 1;
pointer[1] = 2;
is only valid if you have earlier pointed it to some array of type uint32_t with atleast size two or to a block containing uint32_ts defined using malloc as follows:
uint32_t *pointer;
pointer = (uint32_t*)malloc(sizeof(int*SIZE); //SIZE > 2 here
or
uint32_t array[10];
pointer = & array[0]; // also, pointer = array; would also work.
int main(void)
{
int variableA = 5;
int variableB = 3;
int* ptr1 = &variableA; // Pointer1 points to 5.
int* ptr2 = &variableB; // Pointer2 points to 3.
int answer;
answer = (*ptr1) * (*ptr2); // I want to multiply 5*3, but I only have the pointers.
// Answer gets set to [value stored at ptr1(5)] MultipliedBy [value stored at ptr2(3)]
}
Your misconception is that pointers do not refer to values, such as 5 and 3.
pointers refer to variables, such as variableA and variableB; those variables have values which can be accessed and changed via the pointer.But the pointer only refers to the variable, not directly to the value behind it.
I have an array of void-Pointers and want to access the elements (inititialize them), but it do not work:
void* anyptr = ...; //a pointer to something
void* arr = (void*)malloc(sizeof(void*)*10);
int i=0;
for(i=0; i<10; i++)
*(arr+i) = anyptr; //dont work, (arr+n) = anyptr; doesn´t work too
I guess, the reason why this won´t work is that on the left side is the result of element i. But i don´t have an idea how to do this
There are two ways to initialize arrays in C:
On the stack (which will handle memory for you since it will be cleaned up when your function ends)
In the heap (which will require you to handle allocation and freeing on your own).
If you would like to use the stack, you could initialize your array like this...
#define ARRAY_LENGTH 10
void *ptr;
void *arr[ARRAY_LENGTH];
for (int i = 0; i < ARRAY_LENGTH; i++) {
arr[i] = ptr;
}
You can similarly define your array in the heap as follows...
#define ARRAY_LENGTH 10
void *ptr;
void **arr = malloc(sizeof(void *) * ARRAY_LENGTH);
for (int i = 0; i < ARRAY_LENGTH; i++) {
arr[i] = ptr;
}
free(arr);
It is important to remember that an array (besides arrays assigned in the stack, which have some additional attributes such as length) is essentially just a pointer to the first element, and the operation arr[i] is the same as moving i*sizeof(elem) bytes away from the first element, and accessing the memory there. If you would like to get a pointer to the ith index in the array, then you would use notations such as...
void *indexPtr = arr + i;
or
void *indexPtr = &( arr[i] );
In this fashion, an array of void*'s would be of type void **, since the variable is a pointer to the first member of the array, which is a pointer. This can be a bit confusing, but just always try to keep in mind what type the elements of the array are, and creating a pointer to them. So if the array is of type int, then the array would be of type int or int[], but if you are storing pointers to integers, you would initialize an array of type int * in either of these two forms...
int **arr = malloc(sizeof(int *) * ARRAY_LENGTH);
int *arr[ARRAY_LENGTH];
Also note that you are storing pointers, so if you run the code...
int *arr[4];
for (int i = 0; i < ARRAY_LENGTH; i++) {
arr[i] = &i;
}
Although it may seem to be that the values pointed to in the array would be as follows- [0, 1, 2, 3], but in reality it would be [4, 4, 4, 4], since what you actually have is an array of pointers all pointing to the variable i in your function, so whenever you change that, the values pointed to in the array will all be changed.
I hope this helped
You need to change this line
void* arr = (void*)malloc(sizeof(void*)*10);
to this
void** arr = malloc(sizeof(void*)*10);
You can't dereference a void pointer. That's the whole point of void pointers.
Dereferencing a pointer provides you with access to the item that's found at the address the pointer points to. With a void pointer, however, you don't know how large the target object is (is it a 1B character or a 100B struct?). You have to cast it to a specific pointer type before dereferencing it.
Adding (or subtracting) an integer i to a pointer is then defined as adding i-times sizeof(*pointer) to the pointer's content. (You can only tell sizeof(*pointer) if your pointer has a specific type. Pointer arithmetic with void pointers makes no sense).
As for (arr+n)= anyptr;, arr+n is just an address. It's not a value you can assign something to (not an lvalue).