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
Okay, So i Solved these issues. The thing was that the GCC compiler has inbuilt extensions, which allow
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.
First of all, match the types and the conversion specifiers.
sizeof
yields asize_t
type, use%zu
to print that.%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. QuotingC11
, chapter 6.3.2.3,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.You may have an issue with your compiler.
When I compile your code, I get the warning
for the conversion you were asking about. Yes, normally conversion of an
int *
to achar *
is illegal without a cast.(I also got a bunch of warnings about mismatched
printf
formats and arguments, because printingsize_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.
From the latest C11 draft:
§7.16.1.1/2
You are correct inasmuch as C does not define behavior for assignment of a value of type
int *
to an object of typechar *
. This is becauseint *
andchar *
are not "compatible" types, and neither isvoid *
.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.
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.