skip to Main Content

So, I am practicing pointers in detail. I just studied that if we perform operations like –

    int a = 1025;
    int *ptr = &a;
    printf("The size of integer is = %dn", sizeof(int));
    printf("The address = %d, value = %dn", ptr, *ptr);
    printf("The address = %d, value = %dn", ptr+1, *(ptr+1));
    
    char *pointer;
    pointer = ptr;
    printf("The size of character is = %dn", sizeof(char));
    printf("The address = %d, value = %dn", pointer, *pointer);
    printf("The address = %d, value = %dn", pointer+1, *(pointer+1));

This should throw an error in pointer = ptr; because they have a different type, and the way to make this work is by typcasting int *ptr to (char*)ptr.

But somehow, this is working without type casting and here is the output-

The size of integer is = 4
The address = 15647756, value = 1025
The address = 15647760, value = 15647756
The size of character is = 1
The address = 15647756, value = 1
The address = 15647757, value = 4

Why is this working, and not showing an error?

Also, we know that Void Pointers cannot be incremented, like we cannot do void pointer + 1

but when I run this-

    int a = 1025;
    int *ptr = &a;
    printf("The address = %d, value = %dn", ptr, *ptr);
    void *ptr1;
    ptr1 = ptr;
    printf("%dn", ptr1+1);

It returns –

The address = 15647756, value = 1025
15647757

Clearly, the void pointer is getting incremented, which should NOT happen, Please explain this as well?

I am using gcc 9.4.0 version compiler on an 20.04 LTS ubuntu machine.

5

Answers


  1. Chosen as BEST ANSWER

    Okay, So i Solved these issues. The thing was that the GCC compiler has inbuilt extensions, which allow

    int a = 1025;
    int *ptr = &a;
    char *pointer;
    pointer = ptr;
    

    The GCC compiler also allows arithemetic on Void pointers because of another extension though this is NOT allowed by the C standard. Due to this extension, the Void pointers is treated as a char pointer.

    For the GCC to show these errors as warnings, I added -Wall flag in settings.json of my code-runner.

    Next I added the -pedantic-errors to my code-runner extension, and this flag caused the arithmetic on void pointers and illegal pointer assignment to become errors, and now the code does not run.

    Hope it helps anyone, who encounters the same problem.


  2. First of all, match the types and the conversion specifiers.

    • sizeof yields a size_t type, use %zu to print that.
    • use %p to print a pointer type.

    That said, any other pointer type can be assigned (converted) to a char pointer and accessed via the later, this is explicitly allowed. Quoting C11, chapter 6.3.2.3,

    …When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.

    The assignment should produce a warning, you might not have asked your compiler to show the warnings, and when you do, you can also ask the compiler to treat the warnings as errors, to see your desired outcome.

    Finally, regarding the operation on void pointers, you’re right, arithmetic operation on void pointer is not allowed as per C standard, but it might be allowed by a special provision in gcc, where it treats it equivalent to a char pointer.

    Login or Signup to reply.
  3. You may have an issue with your compiler.

    When I compile your code, I get the warning

    warning: incompatible pointer types assigning to 'char *' from 'int *'
    

    for the conversion you were asking about. Yes, normally conversion of an int * to a char * is illegal without a cast.

    (I also got a bunch of warnings about mismatched printf formats and arguments, because printing size_t needs %zu, and printing pointers requires %p.)

    If you’re not getting these warnings, you might try increasing your compiler’s warning level, perhaps with options like -Wall or -Wextra. Although it seems strange to me that you would have to, because in my experience, these warnings are enabled by default. gcc says "enabled by default". clang suggests that you can turn on this specific warning with -Wincompatible-pointer-types, although for me it’s enabled by default.


    You also asked about arithmetic on void pointers. That’s a popular, though controversial, gcc extension. See this question.

    Login or Signup to reply.
  4. From the latest C11 draft:

    §7.16.1.1/2

    ...if type is not compatible with the type of the actual next argument 
    (as promoted according to the default argument promotions), the behavior 
    is undefined, except for the following cases:
    
    — one type is a signed integer type, the other type is the corresponding 
    unsigned integer type, and the value is representable in both types;
    — one type is pointer to void and the other is a pointer to a character type.
    
    Login or Signup to reply.
  5. This should throw an error in pointer = ptr; because they have a different type, and the way to make this work is by typcasting int *ptr to (char*)ptr.

    You are correct inasmuch as C does not define behavior for assignment of a value of type int * to an object of type char *. This is because int * and char * are not "compatible" types, and neither is void *.

    Even interpreting "error" generously, however, there are few situations about which it is correct to say that a C implementation "should throw an error". These are the constraint violations, which C requires conforming implementations to diagnose. And that’s all C requires in those situations. It does not require the implementation to reject the offending program, so if that’s part of what "error" means to you then no, the C language specification provides no basis for saying that any particular code should throw an error.

    Additionally, compilers do not necessarily diagnose all constraint violations by default. GCC is one that does not, but its -pedantic option option requests that it emit all the diagnostics that the language standard requires of conforming implementations (among other things related to conformance to the standard). Or if you want GCC not only to diagnose but also to reject all code containing constraint violations then use -pedantic-errors instead.

    By default, GCC is happy to accept that assignment, and will interpret it as if the needed cast had been provided. This is an extension to standard C.

    Also, we know that Void Pointers cannot be incremented, like we cannot do void pointer + 1

    No. We know that the C language spec does not define behavior for arithmetic with void pointers. That’s not the same thing. GCC, as another extension, does define such behavior, as equivalent to arithmetic on a char *.

    Relying on extensions such as these makes your programs less portable, but undefined behavior is undefined. You cannot rely on the compiler to reject such programs.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search