Operation on void pointer - c

It is known that void pointer airthmetic is invalid.
int main {
int b = 10;
void *a = (void *) &b;
void *c = a + 1;
printf ("%p\n", a);
printf ("%p\n", c);
}
Output:
0x7fff32941d1c
0x7fff32941d1d
I have read that above airthmetic is unexpected behaviour and we cannot rely on it.
Now moving on to actual question. I am taking an array of void pointers.
int main()
{
void *a[10];
void **b = a;
void **c = (a + 1);
printf ("%p\n", b);
printf ("%p\n", c);
}
Output:
0x7fff8824e050
0x7fff8824e058
Can you please explain the above behavior, where a double pointer (pointer to a void pointer is used). Is it expected behavior?

Can you please explain the above behavior, where a double pointer (pointer to a void pointer is used). Is it expected behavior?
Yes, it is expected behavior.
That's because the size of the object the pointer points to is known. It is sizeof(void*).
If the values of the pointers are expressed in purely integral values,
(a + 1) == a + 1*sizeof(void*)
It appears that on your platform, sizeof(void*) is 8.

Related

is there a way we can make functions that return pointers in C?

I mean, can we make functions return pointer like in this code:
#include <stdio.h>
int* sum(int* ptr_1, int* ptr_2){
return (*ptr_1 + *ptr_2);
}
int main() {
int x=0, y=0;
scanf("%d %d", &x, &y);
int *ptr_x = &x;
int* ptr_y = &y;
printf("%d", *sum(ptr_x, ptr_y));
return 0;
}
This code takes 2 int numbers and prints sum of them using pointers. It didn't work on ssh but I wanted to ask anyway.
That code is buggy. It returns the sum of two ints as a pointer which doesn't make sense.
You can return pointers, but they should also point at something (or NULL). Dereferencing the pointer returned by sum (as you do in the printf line) will almost certainly cause undefined behavior.
A contrived but working version of your program:
#include <stdio.h>
int *sum(int *ptr_1, int *ptr_2) {
// `static` makes `result` stored between calls so it isn't destroyed
// when the function returns:
static int result;
result = *ptr_1 + *ptr_2;
return &result; // return a pointer pointing at result
}
int main() {
int x, y;
if(scanf("%d %d", &x, &y) != 2) return 1;
int *ptr_x = &x;
int *ptr_y = &y;
printf("%d", *sum(ptr_x, ptr_y));
}
Yes, functions can return pointers.
Your problem is that the expression *ptr_1 + *ptr_2 yields a value of type int, not int * (each of *ptr_1 and *ptr_2 are ints, so adding them together gives you an int value).
Whatever that integer value is, it's likely not a valid pointer (it's not the address of an object during that object's lifetime), and the behavior on dereferencing an invalid pointer is undefined. Your code may crash, you may get nonsensical output, something else may happen.
Yes, you can return a pointer, but in this specific case, you do not need to, your sum should simply return an int, not a pointer to int:
int sum(int* ptr_1, int* ptr_2){
return (*ptr_1 + *ptr_2);
}

Question about converting `void *` to `int` in C

I'm trying to pick my C skills again. I want to sum a sequence in different threads, each thread would return a pointer of the sum of a part of the sequence. However, when I tried to convert the void* type value local_sum to int, problem occurred.
I tried to convert with sum += *(int*)local_sum;, a segment error occurred and I got Process finished with exit code 11.
I found that if I use sum += (int)local_sum;, it would be okay. But I couldn't convince myself: shouldn't local_sum be a void *? Why it can be converted to int with (int)local_sum?
I'm so grateful it you could answer the problem.
The part that sum each process's return value is here:
int sum = 0;
for (int i = 0; i < NUM_THREADS; i ++) {
void * local_sum;
pthread_join(count_threads[i], (&local_sum));
sum += (int)local_sum;
}
The function of a thread is here:
void * count_thr(void *arg) {
int terminal = ARRAY_SIZE / NUM_THREADS;
int sum = 0;
for (int i = 0; i < terminal; i ++) {
sum += *((int*)arg + i);
}
return (void*)sum;
}
You're returning the value of int sum by setting a void * address to it. In this case, the address is not valid. But, if you keep that in mind and get the value of sum by casting a void * to int it will work.
void * is used this way sometimes to return either a value (e.g. int) or an address to something (e.g. struct).
To illustrate this:
int a = 5;
void *p = (void *)a;
int b = (int)p;
a, p, and b all have a value of 5. p does not point to a valid address. Trying to dereference p would result in undefined behavior:
b = *(int *)p; // Undefined Behavior!
Consider the following program:
#include <limits.h>
#include <stdio.h>
int main(void)
{
int a, b;
void *p;
a = 5;
p = (void *)a;
b = (int)p;
printf("%d %p %d\n", a, p, b);
a = INT_MAX;
p = (void *)a + 1;
b = (int)p;
printf("%d %p %d\n", a, p, b);
return 0;
}
When compiled, I get the following warnings:
$ gcc main.c -o main.exe
main.c: In function ‘main’:
main.c:9:9: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
p = (void *)a;
^
main.c:10:9: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
b = (int)p;
...
A warning is issued because, as pointed out by #Gerhardh, the sizeof(int) and the sizeof(void *) may be different. You may suffer data loss if the value of the void * exceeds the maximum value a int can hold.
Output
$ ./main.exe
5 0x5 5
2147483647 0x80000000 -2147483648
You can't do *(int*)local_sum because local_sum is not an int* cast to void*. local_sum is an int cast to void*. It is a number reinterpreted as an address, but only for transfer purposes, because pthread_exit only allows you to return a void*, not an int and because the standard explicitly allows implementation-defined conversion (6.3.2.3p5, 6.3.2.3p6) between integers and numbers as long as the values fit (if they don't then, UB). If you return, e.g., 0x42, it is highly unlikely there's anything at address 0x42, so you should forget about dereferencing it and instead you should convert it back to an integer ASAP, either with (int)local_sum; or perhaps better with (int)(intptr_t)local_sum; (though intptr_t isn't guaranteed to exist) or (perhaps best) with (int)(intmax_t)local_sum; so as to avoid possible compiler warnings about converting to an integer of a different size on LP64 platforms.
A secure and portable solution could be the use of an union:
union void_cast {
void* ptr;
int value;
};
Then for example you can safely reinterpret a void* pointer with:
int VOID_TO_INT(void* ptr) {
union void_cast u;
u.ptr = ptr;
return u.value;
}
void* INT_TO_VOID(int value) {
union void_cast u;
u.value = value;
return u.ptr;
}
So your code can be changed to:
sum += VOID_TO_INT(local_sum);

C fat pointer implementation failure

I have discovered a library recently which implements a C++ vector like functionality using fat pointers.
I have tried to replicate a similar behaviour in a short program (see the code below). I can access the array elements fine but when I try to get the number of elements my program prints garbage.
#include <stdio.h>
#include <stdlib.h>
int main()
{
double * a = NULL;
// the data
double b[] = {1, 2, 3, 5};
a = (int *) malloc(sizeof(int) + sizeof(double *));
a[0] = 4;
a++;
a = b;
// will print 1.0 2.0 3.0 5.0
printf("%lf %lf %lf %lf\n", a[0], a[1], a[2], a[3]);
// prints garbage
printf("%d\n", *((int *) a - 1));
// this will fail
free(((int *) a - 1))
return 0;
}
It is likely that the problem lies in the pointer arithmetic part of the code, i.e. (int *) a - 1 points to the wrong address, but I could not figure out why is that the case.
Any help is appreciated.
Packing the length at the beginning of the array is not a fat pointer, but an ill-formed PASCAL array.
int main(fat_pointer);
int main(int argc, char* argv[argc]); // standard signature for main is a fat pointer
A fat pointer is a pointer and an index. The data type of the index is an integral type which guarantees that sizeof index <= sizeof(size_t). In other words, sizeof(int) <= sizeof(size_t) is a mandate for all compliant hosted environment because main demands so. Note that size_t is not defined for freestanding environment.
The problem with _s functions is that they use sal.h from Microsoft which allow the usage of variables before declaration.
char * strcpy_s(char * restrict dest, rsize_t destsz, char const * restrict src);
// fat pointer form fails
char * strcpy_s(char dest[destsz], rsize_t destsz, char const * src);
The fat pointer form fails because destsz is declared afterwards, so it cannot be used. Annex K is horrible because it has usage before declaration in fat pointer form. Look at main where argc is declared before argv; that is the proper way to declare a fat pointer.
#include<stdio.h>
#include<stdlib.h>
void print_vector_double(int len, double d[len])
{
for (int i = 0; i < len; i++)
printf("%lf ", d[i]);
printf("\n");
printf("%d\n", len);
}
int main(int argc, char* argv[argc])
{
// C89 VLA - initialized VLA
double b[] = { 1, 2, 3, 5, };
int b_len = (int)(sizeof b / sizeof b[0]);
print_vector_double(b_len, b);
// C99 VLA - uninitialized VLA
int c_len = b_len;
double c[c_len];
c = b;
print_vector_double(c_len, c);
// Good Old Heap for Dynamic Arrays
int a_len = b_len;
double * a = malloc(a_len * sizeof * a);
double * temp = memcpy(a, b_len * sizeof * b, b);
if (temp != a) exit(EXIT_FAILURE);
print_vector_double(a_len, a);
free(a), a = NULL, a_len = 0;
}
A fat pointer is what you pass to a function. If you are not passing anything to another function, there is no fat pointer.
Cello failed to understand what a fat pointer really is.

Understanding pointers with a swap program in C

I am trying to better understand pointers and referencing in C, and my course provided the following program as an example.
#include <stdio.h>
void swap(int* a, int* b);
int main(void)
{
int x = 1;
int y = 2;
swap(&x, &y);
printf("x is %i\n", x);
printf("y is %i\n", y);
}
void swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
I shambled together the following to see if it would help me understand better what's happening, mainly in regards to the need to use & versus *(dereference). Basically, the syntax of declaring a pointer to int type (int* a) versus using an asterisk to "dereference" (*a = *b) is quite confusing to me, and I was hoping someone could enlighten me. Here's another version of the above that I thought would help clarify, but really doesn't:
#include <stdio.h>
void swap(int* a, int* b);
int main(void)
{
int x = 1;
int y = 2;
int *a = &x;
int *b = &y;
swap(a, b);
printf("x is %i\n", x);
printf("y is %i\n", y);
}
void swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
In short, my question is, is there a functional difference between what these two programs are doing? What is the difference between a dereference (*a = *b) versus using the & operator (*a = &x)".
You're confusing declaration and assignment.
*a = *bis called assignment. Notice it does not include a type name.
int *a = &x on the other hand is called declaration. Notice that you initialize the pointer with the address of x. You are not dereferencing the pointer, but are declaring it as a pointer to int.
Look at this:
int main() {
int a = 5;
int b = 2;
int *c = &a; // c when dereferenced equals 5; **Declaration**
int *d = &b; // d when dereferenced equals 2; **Declaration**
int tmp = *c; // tmp equals 5
*c = *d; // c when dereferenced now equals 2 **Assignment**
*d = tmp; // d when dereferenced now equals 5 **Assignment**
return 0;
}
Finally, when you declare and initialize a pointer in the same statement, you assign the pointer the address of what you want to have point at it. When you want to change the value the object points to, you dereference it using *. On the other hand, if you want to change what it points to, you do not dereference it.
&xreturns the address of x. x is of type integer and a is of type pointer to integer. In this case, (*a = &x), you are assigning the address of x to a variable of type "pointer to integer", which is a. (*a = *b) is a assign operation between two variables of the same type which is integer. I said integer because even though a and b are "pointers to integers", in that operation they are dereferenced and therefore the integer value to which these are pointed to is read.
The confusion I think you have is because (*a = &x) only makes sense during a pointer initialization.
If you set *a = *b since a and b are pointer variables, the * operator will retrieve the value of a cell in memory that b points to it and puts it to the cell that a points to it.
For *a = &x, the & operator finds the address of the cell that allocated to the x variable, and puts it in the cell that a points to it.
In short, my question is, is there a functional difference between
what these two programs are doing?
No, the functional effect is exactly the same. In
int *a = &x;
int *b = &y;
swap(a, b);
// swap(&a, &b)
The type of a is the same of &a, namely int* (pointer to int). The only difference is that you're using other variables to store that, which is not really needed logically but it is absolutely fine to have it, especially if it could help you understand the syntax.
What is the difference between a dereference (*a = *b) versus using &
(*a = &x).
*a = *b assigns the value pointed to by b (obtained with *b) in the ones pointed to by a. To see it more clearly,
int tmp = *b;
*a = tmp;
&(*a = &x) is not a valid expression because you can't store an address into an int (actually you can, but that's beyond the point).

Why my program not working?

#include"stdio.h"
void print2(int ***b) {
printf("\n %d \n",***b);
***b=14;
printf("\n %d \n",***b); }
void print(int ***b) {
printf("\n %d \n",***b);
***b=11;
printf("\n %d \n",***b); }
void print1(int **b) {
printf("\n %d \n",**b);
**b=12;
printf("\n %d \n",**b); }
int main() {
int p =10; int *q = &p; int **r = &q; int ***a = &r;
printf("\n %d \n",***a);
print(a); //i.e print(&*a);
printf("\n %d \n",***a);
print1(*a); //i.e print1(&**a);
printf("\n %d \n",***a);
print2(**a); //i.e print2(&***a);
printf("\n %d \n",***a);
return 0; }
tptr.c:32:8: warning: incompatible pointer types passing
'int *' to parameter of type 'int ***'
[-Wincompatible-pointer-types]
print2(**a); //i.e print1(&***a); 1000
^~~
tptr.c:2:20: note: passing argument to parameter 'b' here
void print2(int ***b)
I think you are confused by how the stars means different things in a declaration and in expressions.
When you declare
int *q = &p;
you get a variable q of type int * or pointer to integer. The same goes for the declaration of function parameters. A function with the prototype
void f(int *q);
takes a parameter of int * or pointer to int.
When you use the declared variables, you just refer to the variable as q, without the stars. So if you want to pass your pointer to integer q to the function f, which expects a pointer to integer, just say
f(q);
Here, q is the pointer itself. If you want to get at the value pointed at, you must dereference q with the dereference operator, the star: *q.
The rationale behind the declaration syntax is that "declaration mimicks use", and the (primary) use of a pointer is to get at its contents by dereferencing. (It is a bit similar to declaring arrays with a dimension in square brackets, when you use it by looking up values with indices in square brackets.)
The address-of operator (unary &) does the opposite: It takes the address of a variable so that you can store it in a pointer. Your (somewhat contrived) example does this; the values p, *q, **r and ***a all refer to the value of p.
By way of illustration, I've simplified your example a bit:
#include <stdio.h>
void print0(int n)
{
printf("%d\n", n);
}
void print1(int *p)
{
printf("%d\n", *p);
}
void print2(int **p)
{
printf("%d\n", **p);
}
void print3(int ***p)
{
printf("%d\n", ***p);
}
int main()
{
int p = 10;
int *q = &p;
int **r = &q;
int ***a = &r;
print0(p); print1(&p);
print0(*q); print1(q); print2(&q);
print0(**r); print1(*r); print2(r); print3(&r);
print0(***a); print1(**a); print2(*a); print3(a);
return 0;
}
See how the print functions declare their arguments in the same way as they use it. And the variables with x levels of indirection are passed to printx unadorned, i.e. without any stars and without address-of operators.
(You can't take the address of a variable directly more than once, because the address is just a number, not a variable with an address itself. You can, of course, take the address indirectly if it is held in a variable, as in your example.)

Resources