Pointer arithmetic for void pointer in C

前端 未结 8 1101
执念已碎
执念已碎 2020-11-22 01:23

When a pointer to a particular type (say int, char, float, ..) is incremented, its value is increased by the size of that data type. I

相关标签:
8条回答
  • 2020-11-22 01:50

    Void pointers can point to any memory chunk. Hence the compiler does not know how many bytes to increment/decrement when we attempt pointer arithmetic on a void pointer. Therefore void pointers must be first typecast to a known type before they can be involved in any pointer arithmetic.

    void *p = malloc(sizeof(char)*10);
    p++; //compiler does how many where to pint the pointer after this increment operation
    
    char * c = (char *)p;
    c++;  // compiler will increment the c by 1, since size of char is 1 byte.
    
    0 讨论(0)
  • 2020-11-22 01:50

    Compiler knows by type cast. Given a void *x:

    • x+1 adds one byte to x, pointer goes to byte x+1
    • (int*)x+1 adds sizeof(int) bytes, pointer goes to byte x + sizeof(int)
    • (float*)x+1 addres sizeof(float) bytes, etc.

    Althought the first item is not portable and is against the Galateo of C/C++, it is nevertheless C-language-correct, meaning it will compile to something on most compilers possibly necessitating an appropriate flag (like -Wpointer-arith)

    0 讨论(0)
  • 2020-11-22 01:51

    You can't do pointer arithmetic on void * types, for exactly this reason!

    0 讨论(0)
  • 2020-11-22 01:57

    You have to cast it to another type of pointer before doing pointer arithmetic.

    0 讨论(0)
  • 2020-11-22 02:05

    The C standard does not allow void pointer arithmetic. However, GNU C is allowed by considering the size of void is 1.

    C11 standard §6.2.5

    Paragraph - 19

    The void type comprises an empty set of values; it is an incomplete object type that cannot be completed.

    Following program is working fine in GCC compiler.

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

    May be other compilers generate an error.

    0 讨论(0)
  • 2020-11-22 02:07

    Final conclusion: arithmetic on a void* is illegal in both C and C++.

    GCC allows it as an extension, see Arithmetic on void- and Function-Pointers (note that this section is part of the "C Extensions" chapter of the manual). Clang and ICC likely allow void* arithmetic for the purposes of compatibility with GCC. Other compilers (such as MSVC) disallow arithmetic on void*, and GCC disallows it if the -pedantic-errors flag is specified, or if the -Werror-pointer-arith flag is specified (this flag is useful if your code base must also compile with MSVC).

    The C Standard Speaks

    Quotes are taken from the n1256 draft.

    The standard's description of the addition operation states:

    6.5.6-2: For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to an object type and the other shall have integer type.

    So, the question here is whether void* is a pointer to an "object type", or equivalently, whether void is an "object type". The definition for "object type" is:

    6.2.5.1: Types are partitioned into object types (types that fully describe objects) , function types (types that describe functions), and incomplete types (types that describe objects but lack information needed to determine their sizes).

    And the standard defines void as:

    6.2.5-19: The void type comprises an empty set of values; it is an incomplete type that cannot be completed.

    Since void is an incomplete type, it is not an object type. Therefore it is not a valid operand to an addition operation.

    Therefore you cannot perform pointer arithmetic on a void pointer.

    Notes

    Originally, it was thought that void* arithmetic was permitted, because of these sections of the C standard:

    6.2.5-27: A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.

    However,

    The same representation and alignment requirements are meant to imply interchangeability as arguments to functions, return values from functions, and members of unions.

    So this means that printf("%s", x) has the same meaning whether x has type char* or void*, but it does not mean that you can do arithmetic on a void*.

    Editor's note: This answer has been edited to reflect the final conclusion.

    0 讨论(0)
提交回复
热议问题