Error dereferencing void pointer

Hi again! In my program i have declared a function with this prototype: Code: int function(void *var) //The second argument is a void * pointer Also i
  • Home
  • Forum
  • General Programming Boards
  • C Programming
  • Warning:dereferencing `void *’ pointer

  1. 04-26-2007


    #1

    g_p is offline


    Registered User


    Warning:dereferencing `void *’ pointer

    Hi again!

    In my program i have declared a function with this prototype:

    Code:

    int function(void *var) //The second argument is a void * pointer
    Also i have a struct 
    
    typedef struct hello hello;
    struct hello
    {
            char *a;
            char *b;
            int  l;
            int  t;
            struct hello *next;
    };
    
    
    hello *pointer_hello;

    When i do: function(pointer_hello);

    I get the warnings:

    warning: dereferencing `void *’ pointer
    test.c:516: error: request for member `a’ in something not a structure or union
    warning: dereferencing `void *’ pointer
    test.c:517: error: request for member `b’ in something not a structure or union
    warning: dereferencing `void *’ pointer
    test.c:518: error: request for member `l’ in something not a structure or union
    warning: dereferencing `void *’ pointer
    test.c:519: error: request for member `t’ in something not a structure or union

    What shall i change in my program?

    Well the problem is that the argument of the function «function» has to be void in order
    not only to take a pointer to a hello struct but to any other struct!

    Thanks, in advance!


  2. 04-26-2007


    #2

    Salem is offline


    and the hat of int overfl

    Salem's Avatar


    It’s impossible to tell, since we need the actual order in which you declared things, and in which file(s) they reside.


  3. 04-26-2007


    #3

    MacGyver is offline


    Deathray Engineer

    MacGyver's Avatar


    My guess is that you are passing a struct pointer to a function that is defined to take a void pointer. You must cast the void pointer to be that of a struct pointer before actually dereferencing it. The compiler has no idea what a void pointer is pointing to. With regard to size, it could be pointing to a byte, a word, a double word, etc. etc. There is no known way of it knowing you are passing it a struct pointer.

    In this case, you must be explicit when dealing with void *’s.


  4. 04-26-2007


    #4

    g_p is offline


    Registered User


    i do

    Code:

    #define  int function( void * var ) ;
    typedef struct hello hello;
    struct hello
    {
            char *a;
            char *b;
            int  l;
            int  t;
            struct hello *next;
    };

    Then it starts

    Code:

    int main() {
    
    hello *pointer_hello;
    function(poinet_hello);
    }

    That’s all!


  5. 04-26-2007


    #5

    g_p is offline


    Registered User



  6. 04-26-2007


    #6

    Salem is offline


    and the hat of int overfl

    Salem's Avatar


    > #define int function( void * var ) ;
    What the hell is this supposed to mean?

    Make function accept an hello* and be done with it.


  7. 04-26-2007


    #7

    g_p is offline


    Registered User


    Quote Originally Posted by MacGyver
    View Post

    My guess is that you are passing a struct pointer to a function that is defined to take a void pointer. You must cast the void pointer to be that of a struct pointer before actually dereferencing it. The compiler has no idea what a void pointer is pointing to. With regard to size, it could be pointing to a byte, a word, a double word, etc. etc. There is no known way of it knowing you are passing it a struct pointer.

    In this case, you must be explicit when dealing with void *’s.

    How can i do this cast?
    can you make an example using the example i have given?

    Thanks, in advance!


  8. 04-26-2007


    #8

    MacGyver is offline


    Deathray Engineer

    MacGyver's Avatar


    Code:

    struct x
    {
    	int a;
    };
    
    ...
    
    int example(void *p)
    {
    	struct x *q;
    
    	if(p)
    	{
    		q = (struct x *)p; /* Explicit cast from a void * to a struct x * */
    		q.a = 5;
    		return 1;
    	}
    	return 0;
    }
    
    ...
    
    int main(void)
    {
    	struct x v1;
    	example(&v1);
    
    	return 0;
    }

    Note: I did not check this code. I would suggest doing what was already suggested: just make your function accept a *hello.


  9. 04-26-2007


    #9

    ssharish2005 is offline


    Registered User

    ssharish2005's Avatar


    dont use void * pointer for this purpose. It looks really messy for evert struct that u wanted to refer you will have to cast it.

    It better u get the argument as struct hello * rather than void *. Which is quite more easy than void. If there are suitation some thing like where a single function need to do the same job for two different struct with same attributes but different names then may be u can think of void pointer.

    ssharish2005


Popular pages

  • Exactly how to get started with C++ (or C) today
  • C Tutorial
  • C++ Tutorial
  • 5 ways you can learn to program faster
  • The 5 Most Common Problems New Programmers Face
  • How to set up a compiler
  • 8 Common programming Mistakes
  • What is C++11?
  • Creating a game, from start to finish

Recent additions subscribe to a feed

  • How to create a shared library on Linux with GCC — December 30, 2011
  • Enum classes and nullptr in C++11 — November 27, 2011
  • Learn about The Hash Table — November 20, 2011
  • Rvalue References and Move Semantics in C++11 — November 13, 2011
  • C and C++ for Java Programmers — November 5, 2011
  • A Gentle Introduction to C++ IO Streams — October 10, 2011

Similar Threads

  1. Replies: 5

    Last Post: 06-26-2008, 10:10 AM

  2. Replies: 15

    Last Post: 06-01-2008, 03:47 PM

  3. Replies: 15

    Last Post: 08-12-2006, 07:12 AM

  4. Replies: 10

    Last Post: 04-09-2006, 03:36 AM

  5. Replies: 20

    Last Post: 10-09-2003, 12:04 PM

What are void pointers in C? 

A void pointer is a pointer that has no specific data type associated with it. Therefore, it can point to a variable of any data type. Void pointers are valid in C.

Declaring void pointers:

void *pointerName;
  • void indicates that the pointer is a void pointer
  • * indicates that the variable is a pointer variable
  • pointerName is the name of the pointer

Let us look at an example of declaring and initializing void pointer in C:

void *ptr;
char ch = ‘N’;
int num = 10;
ptr = &ch;
ptr = #

In the above code, we notice that since ptr is a void pointer, we can make it point to a variable of char type as well as a variable of int type. It can point to any type of variables.
Some important points to remember while using void pointers:

  • A void pointer cannot be dereferenced. We get a compilation error if we try to dereference a void pointer. This is because a void pointer has no data type associated with it. There is no way the compiler can know what type of data is pointed to by the void pointer. The solution is typecasting. To get the data pointed to by a void pointer we typecast it with the correct type of the data held inside the void pointers location.

Let us understand this with a code:

#include<stdio.h>

void main()

{

int num=10;//Intialising a normal varible

void *ptr;//Declaring a void pointer

ptr=#//Making ptr point to num

printf("The value of integer variable is= %d",*ptr );

}

When we run this code, we get a compilation error as follows:

exit status 1
main.c: In function 'main':
main.c:13:49: warning: dereferencing 'void *' pointer
printf("The value of integer variable is= %d",*ptr );
^~~~
main.c:13:49: error: invalid use of void expression

Look at us look at the same code. We use typecasting here to dereference the pointer:

#include<stdio.h>

void main()

{

int num=10;//Intialising a normal varible

void *ptr;//Declaring a void pointer

ptr=#//Making ptr point to num

printf("The value of integer variable is %d", (int)ptr );// Typecasting

}

The output will be:

The value of integer variable is 10

Therefore, by typecasting, we can dereference void pointers.

  • Pointer arithmetic is not allowed with a void pointer, it gives an error.

Uses of void pointers:

  • Void pointers are used in Generic functions in C.
  • malloc() and calloc() functions return void * type. This allows these functions to allocate memory to any data type.

vani2

0 / 0 / 0

Регистрация: 05.12.2010

Сообщений: 20

1

04.04.2011, 22:13. Показов 3932. Ответов 15

Метки нет (Все метки)


Написал программу, но ошибки в присваивании с раскрытием указателя на void.
Google не помог.

В gcc:
new.c: In function `reml_array’:
new.c:10: warning: dereferencing `void *’ pointer
new.c:10: warning: dereferencing `void *’ pointer
new.c:10: error: invalid use of void expression

В Borland 5.02:
Error: new.c(10,23):Not an allowed type
Error: new.c(10,46):Not an allowed type

Подскажите как исправить, чтоб правильно заработало.
(В buffer мы храним «что-то»).
Спасибо.

header:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct array_element {
    void * element;//указатель на значение элемента
    struct array_element * next;
    struct array_element * prev;
};
 
struct array {
    struct array_element * first;
    struct array_element * last;
    int tsize;//размер в байтах элемента массива
    int lowbound;
    int highbound;
    void * buffer;
};
 
typedef struct array * array;
 
void * reml_array(struct array * parray);

new.c:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>
#include "array.h"
 
void * reml_array( struct array * parray ) {
    
    struct array_element *tmp;
    
    tmp = parray -> first;
    *( parray -> buffer ) = *( tmp -> element );
    parray -> first = tmp -> next;
    parray -> first -> prev = NULL;
    ( parray -> lowbound ) ++;
    free ( tmp );
    
    return ( parray -> buffer );
}

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

04.04.2011, 22:13

15

В астрале

Эксперт С++

8048 / 4805 / 655

Регистрация: 24.06.2010

Сообщений: 10,562

04.04.2011, 23:50

2

vani2, нельзя так void раскрывать. только после приведения к конкретному типу.



0



vani2

0 / 0 / 0

Регистрация: 05.12.2010

Сообщений: 20

05.04.2011, 09:24

 [ТС]

3

Хорошо…
Тогда такой вопрос: к какому типу мне приводить, чтобы не терять значение ?
Мне его только выводить нужно, арифметики никакой проводить не требуется.
Попробовал вот так

C
1
strcpy ( ( char * ) (parray -> buffer) , ( char * ) (tmp -> element) ) ;

Выдаёт непонятную ошибку (наверное, всё кроется в отсутствии «»).



0



Делаю внезапно и красиво

Эксперт С++

1312 / 1227 / 72

Регистрация: 22.03.2011

Сообщений: 3,744

05.04.2011, 09:29

4

Цитата
Сообщение от vani2
Посмотреть сообщение

к какому типу мне приводить, чтобы не терять значение ?

А какой тип ты в нём сохранял? Вот к нему и приводи.



0



vani2

0 / 0 / 0

Регистрация: 05.12.2010

Сообщений: 20

05.04.2011, 09:42

 [ТС]

5

В том то и дело, что я наперёд не знаю, какой тип там будет храниться. Лишь знаю array->tsize-размер элемента в байтах.
Приводил к char, т.к. предположил, что копирование по 1 байту подойдёт.

Ещё не могу понять, почему эта функция не работает:

C
1
memcpy ( ( char * ) (parray -> buffer) , ( char * ) (tmp -> element) , parray -> tsize ) ;

/mingw/lib/libmingw32.a(main.o):main.c.text+0xd2): undefined reference to `Win
Main@16′
collect2: ld returned 1 exit status



0



14 / 14 / 1

Регистрация: 04.04.2011

Сообщений: 70

05.04.2011, 09:54

6

для копирования попробуй memncpy



0



0 / 0 / 0

Регистрация: 05.12.2010

Сообщений: 20

05.04.2011, 10:09

 [ТС]

7

Цитата
Сообщение от wolf.diesel
Посмотреть сообщение

для копирования попробуй memncpy

Ты имеешь ввиду memcpy? Над твоим постом результат применения-неудача.



0



14 / 14 / 1

Регистрация: 04.04.2011

Сообщений: 70

05.04.2011, 10:10

8

да, пардон, опечатка.



0



0 / 0 / 0

Регистрация: 05.12.2010

Сообщений: 20

05.04.2011, 13:00

 [ТС]

9

Какие будут ещё предложения?



0



В астрале

Эксперт С++

8048 / 4805 / 655

Регистрация: 24.06.2010

Сообщений: 10,562

05.04.2011, 14:26

10

vani2, В чем суть программы? Если данные разных типов надо хранить — то стоит завести некую структуру тип, а дальше уже через switch…
Что-нибудь вроде https://www.cyberforum.ru/cpp-… 65807.html



1



0 / 0 / 0

Регистрация: 05.12.2010

Сообщений: 20

05.04.2011, 15:24

 [ТС]

11

Я пишу динамический массив произвольного типа.

Цитата
Сообщение от ForEveR
Посмотреть сообщение

Ты тут явно тип указываешь, мне так нельзя ( то есть я не знаю к какому типу приводить, думаю всё к char* писать ). От данной структуры программы я отходить не могу, так что с указателями на void придётся делать.



0



Делаю внезапно и красиво

Эксперт С++

1312 / 1227 / 72

Регистрация: 22.03.2011

Сообщений: 3,744

05.04.2011, 15:48

12

Цитата
Сообщение от vani2
Посмотреть сообщение

думаю всё к char* писать

Не получится. Вернее получится, но потом не удивляйся тому, что увидишь.)



0



vani2

0 / 0 / 0

Регистрация: 05.12.2010

Сообщений: 20

05.04.2011, 16:25

 [ТС]

13

Написал вот так:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
 
int main ( void ) {
    
    void * p, * k;
    
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    
    p = malloc (10);
    k = malloc (10);
    p = (char*) p;
    k = (char*) k;
    
    printf("Ввод: ");
    scanf ( "%s %s", p, k );
    
    printf ( "k = %sn p = %sn", k,p );
 
    strcpy ( p, k );
    
    printf ( "k = %sn p = %sn", k,p );
    
    free ( p );
    free ( k );
    
    return 0;
}

Всё отлично работает. Осталось этот алгоритм в свой проект вставить.
Пишите замечания.



0



Делаю внезапно и красиво

Эксперт С++

1312 / 1227 / 72

Регистрация: 22.03.2011

Сообщений: 3,744

05.04.2011, 17:00

14

Строки 15,16 что делают?



0



wolf.diesel

14 / 14 / 1

Регистрация: 04.04.2011

Сообщений: 70

05.04.2011, 17:14

15

Это бесполезный код.

C++
1
2
p = (char*) p;
k = (char*) k;

Это

C++
1
scanf ( "%s %s", p, k );

Замени на

CSS
1
scanf ( "%s %s", ( char* )p, ( char* )k );



0



Делаю внезапно и красиво

Эксперт С++

1312 / 1227 / 72

Регистрация: 22.03.2011

Сообщений: 3,744

05.04.2011, 17:21

16

Цитата
Сообщение от wolf.diesel
Посмотреть сообщение

Замени на

Заменять не нужно. Тип определяется только формтной строкой.



0



  • Forum
  • Beginners
  • error: invalid use of void expression

error: invalid use of void expression

CodeBlocks…
warning: dereferencing ‘void *’ pointer [enabled by default]|
error: invalid use of void expression

I believe i do not know how to properly use the generic void* pointer. I want to pass data to pointer to void so that to be able to manipulate any type of data the user wants to use. The functions below is just a test to show my intentions.
I am using only c language syntax. I do not want c++ syntax for these.

I have asked a very similar question in the past but i did not quite get it. It was not the kind of response i was hoping for.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>

int foo(void* x, void* y)
{
    *x  = 3;
    *y = *x + 1;
    return 0;
}

void* foo1( void* x)
{ *x = *x +1; }
 
int main(void)
{
    int a=7;
    int b = 5;
    char c = 'a';
    foo(&a,&b);
    printf("%dn%dn",a,b);

    foo1(&c);
    printf("%cn",c);
    
}

e]

In function ‘int foo(void*, void*)’:
5:6: error: ‘void*’ is not a pointer-to-object type
6:6: error: ‘void*’ is not a pointer-to-object type
6:11: error: ‘void*’ is not a pointer-to-object type
In function ‘void* foo1(void*)’:
11:4: error: ‘void*’ is not a pointer-to-object type
11:9: error: ‘void*’ is not a pointer-to-object type
11:15: warning: no return statement in function returning non-void [-Wreturn-type]

Normally when using void pointers, one has to cast the pointer to a type.

http://stackoverflow.com/questions/16986214/why-type-cast-a-void-pointer#16986872

When doing some kind of operation on data the compiler needs to know the type, otherwise it doesn’t know what machine code to generate. For example, addition between two signed 32-bit integers uses a different CPU instruction than addition between two unsigned 16-bit integers, or between two floating point numbers. Addition between two class types requires that the correct overload of operator+ is called, but if the compiler doesn’t know the types there is no way it could know which overload to call.

If you can use C++ features you might find function templates useful. The compiler will then be able to automatically generate code (at compile time) for each type that you pass to it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>

template <typename T>
int foo(T* x, T* y)
{
    *x  = 3;
    *y = *x + 1;
    return 0;
}

template <typename T>
T* foo1(T* x)
{
    *x = *x +1;
    return x;
}
 
int main(void)
{
    int a=7;
    int b = 5;
    char c = 'a';
    foo(&a,&b); // calls foo<int>
    printf("%dn%dn",a,b);

    foo1(&c); // calls foo1<char>
    printf("%cn",c);
}

Last edited on

Cast your pointer to the desired type before manipulating it.

The problem with foo() is that there are non-enforceable requirements on the real type of the pointed-to object. You either need to know the type is (i.e., by passing it in as a macro parameter or via a printf-style specifier), or you need to make assumptions about the type based on its size, and you’d have to pass the size in.

The real solution is to not use void* here. Generic programming in C is awful.

Is something like this what you’re thinking of?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/* Some way to signal the real type of an argument.  Such a type is analogous to
   printf's format string -- that's one way to signal type too. */
/* User-defined structures will need to be handled through a proxy function */
typedef enum TypeLabel { Char_T, SChar_T, UChar_T, Int_T, UInt_T, /* ... */ } TypeLabel;
void increment(TypeLabel c, void* x) {
# if ! defined BRANCH
# define BRANCH(label, type) do {                      
    /* Manipulate x here */                            
    case label: *((type*)x) = (*(type*)x) + 1; return; 
  } while(0)

  switch (c) {
    BRANCH(Char_T , char);
    BRANCH(SChar_T, signed char);
    BRANCH(UChar_T, unsigned char);
    BRANCH(Int_T  , int);
    BRANCH(UInt_T , unsigned int);
    /* ... */
  }
# else
# error "BRANCH already defined"
# endif 
}

# include <stdio.h>
int main(void) {
  int bar = 3;
  increment(Int_T, &bar);
  printf("%dn", bar);
}

http://coliru.stacked-crooked.com/a/5c5f42258e8f2c92

Last edited on

Topic archived. No new replies allowed.

In this article, we will learn what is void pointer in C and how we can use void pointer in our C code. If you are new in c programming, you should read this article “C pointer concept“. In the C language pointer is used to store the address of any variable or function but we need to remember that types of the pointer should be the same as the types of the pointed object (variable, pointer, array, function …etc.).

For example, if you want to store the address of the character, the pointer should be a pointer to the character.

char cData;

char *pcData = NULL;

pcData = &cData;

To resolve the above problem, C language introduces a generic type of pointer (void pointer) that can store the address of any type.

What is void pointer in C?

A void pointer in c is called a generic pointer, it has no associated data type. It can store the address of any type of object and it can be type-casted to any type. According to C standard, the pointer to void shall have the same representation and alignment requirements as a pointer to a character type. A void pointer declaration is similar to the normal pointer, but the difference is that instead of data types we use the void keyword.

Syntax:

void * Pointer_Name;

Example,

void *pvHandle;

What is the size of a void pointer in C?

The size of a void pointer is similar to the size of the character pointer. According to C standard, the pointer to void shall have the same representation and alignment requirements as a pointer to a character type.

The size of the pointers depending on the platform and it can be 2bytes, 4bytes or 8bytes …etc.

Let’s see some example code.
#include <stdio.h>

int main(int argc, char *argv[])
{

    void *pvData = NULL; //void pointer

    int *iData  = NULL;// integer pointer

    char *cData = NULL;//character pointer

    float *fData = NULL;//float pointer



    //size of void pointer
    printf("size of void pointer = %dnn",sizeof(pvData));


    //size of void pointer
    printf("size of integer pointer = %dnn",sizeof(iData));

    //size of void pointer
    printf("size of character pointer = %dnn",sizeof(cData));

    //size of void pointer
    printf("size of float pointer = %dnn",sizeof(fData));

    return 0;
}

Output: On a 32-bit machine

size of void pointer = 4

size of integer pointer = 4

size of character pointer = 4

size of float pointer = 4

Dereferencing a void pointer in C

Using the indirection operator (*) we can get back the value which is pointed by the pointer, but in case of void pointer we cannot use the indirection operator directly. This is because a void pointer has no data type that creates a problem for the compiler to predict the size of the pointed object. So before dereferencing the void * we have to typecast it, it enables the compiler to predict the data types.

Let’s see some example code.
#include <stdio.h>

int main(int argc, char *argv[])
{

    void *pvData;

    int iData = 10;


    pvData = &iData;

    printf("*pvData = %d",*pvData);

    return 0;

}

Explanation: When we compile the above code, we will get the compiler error because in the above code I tried to dereference the void pointer without type casing.

But what happened if we type-cast the void pointer, its working fine see the below example code.

#include <stdio.h>

int main(int argc, char *argv[])
{

    void *pvData;

    int iData = 10;


    pvData = &iData;

    printf("iData = %d",*(int*)pvData);

    return 0;
}

Output: 10

In the above code void pointer, pvData is pointing to the address of iData (integer variable). So to access the value of integer variable (iData) through the void pointer we have to typecast void pointer through the integer pointer.

(int *)pvData;

Now above expression behave like an integer pointer. You already know how to dereference an integer pointer using an indirection operator (*).

*(int *)pvData

Now you will get the value of the integer which addresses pointed by the void pointer.

Why are void pointers use?

A very important feature of the void pointer is reusability. Using the void pointer we can store the address of any object and whenever required we can get back the object through the indirection operator with proper casting.

Let’s take an example,
#include <stdio.h>

int main(int argc, char *argv[])
{

    void *pvData;

    int iData = 10;
    char cData = 'A';
    float fData = 27.6;

    //Assigning address of character
    pvData = &cData;

    //dereferencing void pointer with character typecasting
    printf("cData = %cnn",*((char*)pvData));



    //Assigning address of integer
    pvData = &iData;

    //dereferencing void pointer with integer typecasting
    printf("iData = %dnn",*((int *)pvData));



    //Assigning address of float
    pvData = &fData;

    //dereferencing void pointer with float typecasting
    printf("fData = %fnn",*((float *)pvData));

    return 0;
}

Output:

cData = A

iData = 10

fData = 27.600000

Explanation: In the above code, pvData is a void pointer. Using it I am storing the address of the different variables (float, int, and char) and after that getting back their values using the indirection operator and proper typecasting.

You can see in the example code, how a single pointer is dealing with different types of variables. This is a very interesting feature of the void pointer that makes the programmer helpless to use the void pointer.

If you want to learn more about the c language, here 10 Free days (up to 200 minutes) C video course for you.

C tutorial

Arithmetic operation on void pointers

Here I want to mention an important point about the arithmetic operation on a void pointer. If you will directly perform an arithmetic operation on the void pointer you may get unexpected results. So you should perform proper typecasting on the void pointer before performing the arithmetic operation.

#include<stdio.h>

int main()
{
    //integer array
    int aiData[3] = {100, 200,300};

    //assigned first element address to the void pointer
    void *pvData = &aiData[0];

    printf(" pvData = %lun", pvData);

    printf(" pvData+1 = %lun", pvData +1); //Incorrect

    return 0;
}

When you will run the above code you will get the unexpected result.

Since the array (aiData) is the collection of integer element so the type of &aiData[0] would be a pointer to int (int*). So we have to typecast the void pointer pvData from the pointer to int (int*) before performing an arithmetic operation.

#include<stdio.h>

int main()
{
    //integer array
    int aiData[3] = {100, 200,300};

    //assigned first element address to the void pointer
    void *pvData = &aiData[0];

    printf(" pvData = %lun", pvData);

    printf(" pvData+1 = %lun", (int*)pvData +1); //Correct

    return 0;
}

Output:

void Arithmetic

You can see, showing the correct value. In my case, the integer size is 4 byte.

Application of void pointer in C 

Application of void pointers are very wide, we can not cover all the application in one article. Here I am taking one of the most popular applications of the void pointer in qsort function.

A qsort is a C standard library function that is used to sort arrays. Using the qsort function, we can sort the array of integer, double, long, etc.

Following is the declaration for qsort() function,

void qsort(void *arr, size_t elements, size_t size, int (*comp)(const void *, const void*));

Parameters of qsort:

arr − pointer to the first element of the array.

elements  − number of elements in the array.

size − size(in bytes) of the element in the array.

comp − compare function that is used to compares two elements.
int comp(const void* a, const void* b);

Let see an example code to understand the working of qsort and importance of void pointer:

In this example code, I am showing how is the qsort function sort any type of array with the help of compare function.

#include <stdio.h>

#define ELEMENT_SIZE(x)  sizeof(x[0])
#define ARRAY_SIZE(x)  (sizeof(x)/sizeof(x[0]))


//compare function for intger array
int compareInt(const void *a, const void *b)
{
    int x = *(const int *)a;
    int y = *(const int *)b;

    if (x < y)
        return -1;  //-1 for ascending, 1 for descending order.
    else if (x > y)
        return 1;   //1 for ascending, -1 for descending order.

    return 0;
}

//compare function for float array
int compareFloat(const void *a, const void *b)
{
    float x = *(const float *)a;
    float y = *(const float *)b;

    if (x < y)
        return -1;  //-1 for ascending, 1 for descending order.
    else if (x > y)
        return 1;   //1 for ascending, -1 for descending order.

    return 0;
}

int main(int argc, char *argv[])
{
    //Integer array
    int iData[] = { 40, 10, 100, 90, 20, 25 };

    //float array
    float fData[] = {1.2,5.7,78,98.5,45.67,81.76};
    //array index
    int index = 0;

    //sorting integer array
    qsort(iData,ARRAY_SIZE(iData),ELEMENT_SIZE(iData),compareInt);
    for (index=0; index<ARRAY_SIZE(iData); index++)
    {
        printf ("%d ",iData[index]);
    }

    printf("nn");
    //sortig float array
    qsort(fData,ARRAY_SIZE(fData),ELEMENT_SIZE(fData),compareFloat);
    for (index=0; index<ARRAY_SIZE(fData); index++)
    {
        printf ("%f ",fData[index]);
    }

    return 0;
}

Output:

10 20 25 40 90 100

1.200000 5.700000 45.669998 78.000000 81.760002 98.500000

Disadvantages of the void pointer in C

  • Like the other pointers, we cannot dereference the void pointers because the compiler does not have any information about the pointed object. If we try to compile the below code then we will get the compiler error.
#include<stdio.h>

int main()
{
    int iData = 100;
    
    void *piData = &iData;
    
    printf("%d", *piData);
    
    return 0;
}

But with proper typecasting, we can dereference the void pointer and get back the value of the pointed address.

#include<stdio.h>

int main()
{
    int iData = 1000;
    void *piData = NULL;
    
    piData = &iData;
    
    printf("%d", (*(int*)piData));
    
    return 0;
}
  • According to c standard arithmetic operation on void pointers is illegal that means the C standard doesn’t allow pointer arithmetic with void pointers. However, In GNU C, addition and subtraction operations are supported on void pointers to assuming the size of the void is 1.
#include<stdio.h>
int main()
{
    int aiData[3] = {100, 200,300};

    void *pvData = &aiData[1]; //address of 200

    pvData += sizeof(int);

    printf("%d", *(int *)pvData);

    return 0;
}

Output: 300 or compiler error.

Explanation: When we compile the code then some compiler throw the compiler error but some compiler compiled the code and print 300 as output to assume the size of the void 1.

Note: Don’t perform the arithmetic operation on the void pointer. As per the C standard sizeof is not applicable on void but in GNU C we can calculate the size of the void and sizeof operator return 1.

Advantages of the void pointer in c

  • Using the void pointer we can create a generic function that can take arguments of any data type. The memcpy and memmove library function are the best examples of the generic function, using these function we can copy the data from the source to destination.

Below code shows the implementation of memcpy in C

int Memcpy(void* dst, const void* src, unsigned int cnt)
{
    uint8_t *pszDest = (uint8_t *)dst;

    const uint8_t *pszSource =( const uint8_t*)src;

    while(cnt)
    {
        *(pszDest++)= *(pszSource++);
        cnt--;
    }

    return 0;
}

Using the memcpy we can copy the string, as well as the array of integers, see the below example codes.

#include<stdio.h>

int main()
{
    char *pszMessage  = "Welcome to aticleworld!";//Source String

    char aszDisplayMessage[32]= {0}; //Destination string

    short siLenString=0;  //

    siLenString = strlen(pszMessage)+1; // length of source string

    Memcpy(aszDisplayMessage, pszMessage,siLenString );//copy source to destination

    printf("Message = %sn", aszDisplayMessage);

    return 0;
}
#include<stdio.h>

int main(void)
{

    int iLoop = 0;
    int aiSrc [5]  = {100,200,300,400,500};//integer array
    int aiDst[5]= {0}; //Destination array

    Memcpy(aiDst, aiSrc,sizeof(aiSrc));//copy integer array

    for(iLoop =0; iLoop <5 ; iLoop++) //print
    {
        printf("%d ",aiDst[iLoop]);
    }
    return 0;
}

You can see how memcpy is working here as a generic copy function with the help of a void pointer.

  • We know that void pointer can be converted to another data type that is the reason malloc, calloc or realloc library function return void *. Due to the void * these functions are used to allocate memory to any data type.
  • Using the void * we can create a generic linked list. For more information see this link: How to create generic Link List.

You want to learn more about C Pointers, you can check the below articles.

  • A brief description of the pointer in C.
  • Dangling, Void, Null and Wild Pointers
  • Function pointer in c, a detailed guide
  • How to use the structure of function pointer in c language?
  • Function pointer in structure.
  • Pointer Arithmetic in C.
  • 10 questions about dynamic memory allocation.
  • Memory Layout in C.
  • 100 C interview Questions
  • File handling in C.
  • C format specifiers.

I have some functions which take as i/p a buffer (it can be float, char,
or 16 bit, int etc.). The result is another o/p buffer, its type is also
flexible (it could be a float, char etc.).

I try to pass both as «void *buf» so that it can accept any data type.
But since I access the buffer and try to assign its elements to another
I get compile errors (I have pasted at the end).

Now my question is how can I pass the i/p and o/p buffers as args to the
function without hardcoding the data type, someone earlier suggested to
pass another argument which tells the type, e.g.
myfunction(void * buf, 1, …) 1 may indicate that buf is char type, 2
means 16 bit etc.

But that means having if .. else’s inside the function to do the same
thing. Is there any other way?

Here is a bit pattern, 32 bits long:

11000101001110101001110101000110

What does it mean? What value(s) does it represent?

Does your answer change if I tell you it is the raw bits of a 32-bit
«float»? What if I say it is a 32-bit VAX float, or perhaps a 32-bit
SPARC float? Suppose I say it is, instead, a 32-bit «int», or a
32-bit «signed int». Now what value(s) can it represent? What if
it is an array of four «char»s or four «unsigned char»s?

(Finding answers — there may be more than one — to the above
questions is a good and useful exercise, that will help you understand
how the system(s) you use interpret bits. Note that different
systems interpret the same bits differently! One reason we use
«high level» source code — although C is relatively low level for
a high level language — is to avoid having to specify the precise
set of bits, which change from system to system, when we can get
away with specifying only what we want the bits to mean. The
source-code number «3.1415» or «42» has a definite meaning, and
the fact that machines A and B use different bit-patterns to
represent them is — we hope — irrelevant.)

Note that all of these are 32 bits long. They all look exactly the
same when treated as a 32-bit-long bit-string. But they all represent
different values.

When you use «void *» in C, you are — usually — implicitly using
a «bag of uninterpreted bits» type. Any interpretation necessarily
arises from giving the «bag of bits» some more-specific type. You
must decide whether you intend to interpret the bits, and if so, how.
This will dictate the type(s) you must provide.

Note that a series of if/else’s, or a switch, inside a function
that receives a «void *» but wants to interpret the bits as one
of (say) the two possibilities «int» and «float» will result in C
code looking like:

enum whichtype { TY_INT, TY_FLOAT };
/*
* Here p points to the first bit(s) in the bag-o-bits, «len»
* is the number of items of some interpreted type, and «ty»
* is the enumeration saying which type.
*/
void f(void *p, size_t len, enum whichtype ty) {
size_t i;
int *ip;
float *fp;

switch (ty) {
case TY_INT:
ip = p;
… work with ip, where i is between 0 and len-1, e.g:
for (i = 0; i < len; i++)
ip *= 2;
break;

case TY_FLOAT:
fp = p;
… work with fp, where i is between 0 and len-1 …
for (i = 0; i < len; i++)
fp *= 2.0;
break;

default:
panic(«invalid type argument %d to f()», (int)ty);
/* NOTREACHED */
}
}

Not only do you really, truly have to write the if/else or switch,
you will also find that, on typical machines, it compiles to code
that uses different machine instructions to manipulate the data.
The code using ip might look like, e.g.:

# this doubles ip, where i is in %eax and ip is in %edx
movl (%edx,%eax,4),%ecx
addl %ecx,%ecx
movl %ecx,(%edx,%eax,4)

versus:

# this doubles fp, where i is in %eax and fp is in %edx
flds (%edx,%eax,4)
fadds (%edx,%eax,4)
fstps (%edx,%eax,4)

These completely-different machine instructions are utterly necessary
here — using the «addl %ecx,%ecx» instructions will not result in
doubling a «float» value in fp, but rather will just make a mess
of the value.

Thus, different C code is required because different machine code
is required. Using «void *» absolves neither you nor the compiler
of this.

If you do enough of this sort of thing (or analyse your systems
carefully), you will find that there are cases where the C source
code must be different, yet the underlying machine code on your
machine(s) is the same. This happens because (and when) the abstract
meaning defined in C for two different types happens to be implemented
using a single underlying machine-level mechanism. But in general,
the C code should remain separate, because on some *other* machine(s),
this may no longer be the case. In other words, in the C code,
you write *what* you want to have happen, not *how* to *make* it
happen. If you want different things, at the C level, that all
happen to be done the same way at the machine level, it is the
compiler’s job to discover this and optimize the code appropriately.
(Some compilers are better than others at this, and you may sometimes
find yourself having to «help» some compilers a bit. Do this only
when you really know what you are doing. :) )

void has no value and no size. It’s a placeholder for nothing basically.

void* is a pointer to an address in memory, but the language doesn’t know how the value there is supposed to be interpreted, because the programmer told it «a nothing is at this address» by making it a void pointer.

Dereferencing a pointer gives you the value of what’s being pointed at. If you have a char* cp, *cp gives you the value of the char at cp. But void doesn’t have value, so the compiler can’t give you anything.

void* is typically used to point to data that could be anything, but had to be treated as nothing, usually because its proper type couldn’t be known (in every compilation unit) at compile time. So we cast it to a pointer of the right type in the compilation unit that knows what type the data there is supposed to be.

C++ added a new type std::any to solve this problem of «pointing at nothing because it could be anything», because it was a type safety nightmare. std::any is basically just a wrapper around void* and std::type_info with a new type-safe casting function std::any_cast<T>. It’s a relatively recent addition so plenty of legacy void* code is still around. You still need to cast it appropriately with std::any_cast to use the data though.

Понравилась статья? Поделить с друзьями:
  • Error dependency pixman 1 not found tried pkgconfig
  • Error dependency is not satisfiable
  • Error dependency colorama is missing install via pip3 install colorama
  • Error dep policy is not enabled due system configuration
  • Error delta double java