Confused by pointers and generic pointers in C

I missed a couple of classes and don't really understand the current examples of lecture slides on the void pointer.

  • In the line "no, no, no", why can not we relate to P, since P was assigned the actual type of pointer q?

  • In the string "?", Is it legal to point to a pointer to an integer? (I think it can compile because C does not check the cast, but does not know what result it will get.

in this example Convert an integer pointer to an integer
it is cast * p = 10; a = (int) p; and someone replied that it would be of great value. but in my case is (int) * p ... Is this the same case as the example I gave above?

  1. In the last line, I am confused by this expression. Is * ((int *) p) actually = p? Thanks!

enter image description here

enter image description here

+5
source share
4 answers

"void *" means "this value is a pointer to something, but I am not telling you what it points to." Start with this statement, and everything makes sense.

So, it should be clear that you cannot dereference emptiness *, because no one told you that points to it! If you don’t know if it points to an int, char or some structure, what do you think should happen if you look for it?

In C, you can assign void * to any pointer, for example, int *. The compiler does not know what void * indicates, but when you write r = p; the compiler says: β€œI hope you know what you are doing, I trust you” (the C ++ compiler does not trust you in the same situation). If void * p really points to int, everything is fine. Otherwise, everything becomes more or less bad.

one is wrong. You cannot play * p. It doesn't matter what you do afterwards, * p is not allowed. And no pointer is passed to an integer. There is an attempt to dereference a pointer that is not allowed. The dereferencing result may not be useful, because you do not know what p points to, so you have nothing to attach to int.

Now what happens in * (int *) p: p is void * is a pointer to something, but you don't know what it points to. (int *) p is cast: p is converted to int *. This means that the compiler will assume that (int *) p points to int - this may or may not be true. * (int *) p dereferences int *: Thus, you convinced the compiler that p points to int, and read the int, which, hopefully, points to. If p really points to int, that's fine. If p does not point to int, you have problems.

+6
source

Void pointers are pointers that do not have a data type associated with them. You must rewrite them to a specific type (Ie: int *) in order to access their contents.

To clarify your specific points:

1) Although p may have a pointer address, it does not have a specific data type associated with it (the data type is required to access the content)

2) The result of this action is probably deterministic in content. I would not recommend this as a good practice.

3) This tells the compiler to treat the void pointer as an integer pointer. Therefore, he "knows" the data type associated with it and refers to it as an int.

+3
source

In the line "no, no, no", why can not we respect P, since P was assigned the real type of pointer q?

int a =2, *q = a, *r; //line 1 void *p; //line 2 p = q; // line 3 r = p; // line 4 

Using line 3 above, you assign the pointer q to p . But it does not change the type of p - it is still a pointer to the void. Therefore, you cannot play it. Therefore, the following is not permissible:

 printf("%d\n", *p); // p is a void pointer - dereferencing here is illegal 

Alternatively, you can:

 printf("%d\n", *((int*) p)); // p is a void pointer 

The above is true. Because we translate p to int * before dereferencing. Consider an example

 void func(void *p) { // what `p` point to here? } int main(void) { int i = 5; long x = 10; void *p; p = &i; // line 1 p = &x; //line 2 func(p); } 

You can comment on line1 or line2, but still in func() know if p points to long or int data? This is no different from your case.

But before accessing the data that it points to, conversion from void * to type * (data pointer) is always required. Please note that this cannot be a data pointer. For instance,

 int i = 42; float f = 4.0; void *p = &f; printf("%d\n", *((int*))p); // wrong! 

It's illegal. p points to a float * . The dereferencing parsing, as if it were pointing to int data, is incorrect.


In the string "?", Is it legal to point to a pointer to an integer?

 printf("%d\n", (int) *p); 

Since p is void* , you are not allowed to play in the first place. Casting after dereferencing does not change anything, and dereferencing is illegal.

If you were to point the pointer like:

 printf("%d\n", (int)p); 

This implementation-defined behavior in C. C also provides intptr_t / uintptr_t for converting integers to pointers.

+3
source

If the pointer p is of type void * , then the expression *p is of type void , and the type of void not 1 ; why do you need to convert a pointer to a "real" type of pointer before dereferencing it.

Pointers and integers can be converted to each other, but values ​​are not guaranteed. However, this is not what the line marked ?? does ; he tries to dereference p and say the result, but since p is a pointer to void , this is not allowed.

The expression *((int *) p) distinguishes p from a pointer to void to a pointer to int and casts the result. Since p points to a , this estimates the value of a ( 2 ).


1. The void type is an incomplete type that cannot be completed.
+1
source

Source: https://habr.com/ru/post/1237528/


All Articles