0

I have a question about coding styles when using void pointers.

This code is modified from code geeks

#include<stdio.h>
int main()
{
    int a[2] = {1, 2};
    void *ptr = &a;
    for(int i=0; i<2; i++) {
        printf("%d\n", *(int *)ptr+i);
    }
    return 0;
}

I am using a generic circular buffer in my project. This buffer has a void pointer to a static buffer which is passed in during initialization. I want to traverse and print the data in the circular buffer. I was unsure how to print the contents until I found the code above.

I have two questions:

  1. Is this an appropriate well accepted way to traverse my data? Will tools such as PC-Lint throw a warning with good reason?
  2. Is there a better way to traverse this data?

Edit: Thanks to Lev M. I have updated my code to properly traverse the data using the size of the data type. The circular buffer is meant to be generic meaning we pass in a buffer and a data type size.

The updated test code is as follows.

#include<stdio.h>
int main()
{
    int a[2] = {2, 1};
    void *ptr = &a;
    for(int i=0; i<2; i++) {
        printf("%d\n", *(int *)ptr);
        ptr = ptr + sizeof(int);
    }

    return 0;
}
13
  • 5
    Why are you using the void pointer in the first place? Use int *ptr = a;. Note also that you don't need & -- the array decays to a pointer to the first element. Commented Mar 9, 2022 at 21:35
  • In my example I noted I am using a generic circular buffer. The ints here are just for show. Commented Mar 9, 2022 at 21:42
  • The generic code wouldn't have an explicit cast to int *, since it needs to work with any type. Take a look at how qsort() works. It gets a void* pointer and the size of the elements. It converts it to char* so it can add the size to the pointer to traverse. The actual type is used only in the comparison function, which has to be specific to the type. Commented Mar 9, 2022 at 21:45
  • 1
    @AndrewHenle That's the "comparison function" that I mentioned in my comment. Commented Mar 9, 2022 at 22:25
  • 1
    Note that even if you solve the traversal problem, you run into another problem: You can't print the data if you don't know the type. Commented Mar 9, 2022 at 22:30

2 Answers 2

2

There is a major bug in your code:

printf("%d\n", *(int *)ptr+i);

The operator precedence means this statement will first do *(int*)ptr than add 2 to the value in the first cell of the array.

If you actually wanted to traverse the array, you would need to do this:

printf("%d\n", *(int *)(ptr+i));

But, that would immediately throw a compiler warning:

warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arith]

This is for a very good reason: to do pointer arithmetic, your compiler needs to know the size of the data being pointed to.
But void has no size for its data, there for this is illegal in standard C.

It is supported by some compiler extensions: http://gcc.gnu.org/onlinedocs/gcc-4.8.0/gcc/Pointer-Arith.html

But note than in case of GCC, the size is 1, so your array will be treated as array of char not int.

How to traverse the buffer in your application will depend on whether the data in it is uniform or not.

You will need to present actual data example if you want a working traversal solution.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your comprehensive answer. I now understand the issue and have used the example given and your answer to update my code. I will edit my question to reflect this.
I think the correct expression is *((int *)ptr + i) or ((int *)ptr)[i]
0

I'm not sure what you want to do we this array but basically the way you can't 'use' void* unless you convert it to its true type. To do so what you wrote above is just fine ((int*)ptr) once you did that you can use this to do any legal operation you want with this 'int' pointer.

1 Comment

I do not think what I want to do matters, the question remains valid. Is there a different way to do this? Is this code "safe"? Will tools such as PC-Lint throw warnings?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.