Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

267
Views
Why is implicit pointer of pointer to pointer conversion legal?

I recently came across some code on stackoverflow where pointers to pointers where used to change allocated memory. While checking the code I made the mistake to add an ampersand to a pointer so make a pointer to a pointer still the compiler happily compiled and runtime errors occured. As an example

#include <stdio.h>

void func(int **p) {
  printf("Pointer is at %p\n", p);
}

int main(void) {
  int *p = 0;
  func(p);
  func(&p);
  int **pp = &p;
  func(&pp);
  return 0;
}

I do understand that C has significantly lower restrictions for pointers than C++ and allows something like char *buf = malloc(SIZE) while not allowed in C++. I see it as a convenience because it happens so much in C.

Nevertheless, I think that the amount of references is a great source of errors and I wonder why one might allow this especially since int is different from int*. Furthermore I want to know if the C standard says something about this.

EDIT I compiled it under ideone.com which likely does not show warnings. My local clang compiler as well as gcc do give warnings. Still, why are they just warnings when they represent different things.


PS, I feel like something like this should have been asked in the last six years of SO. If this a duplicate I am sorry for not finding one.

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

The conversion is not legal. More precisely, there is no implicit conversion from int* to int**, or from int*** to int**. Attempting to pass an int* or an int*** to a function that requires an int** argument is a constraint violation; any conforming compiler must diagnose it. (The diagnostic message may be a non-fatal warning.)

When I compile your code with gcc, even with default options (which makes gcc non-conforming), I get several warnings:

c.c: In function ‘func’:
c.c:4:3: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘int **’ [-Wformat=]
   printf("Pointer is at %x\n", p);
   ^
c.c: In function ‘main’:
c.c:9:3: warning: passing argument 1 of ‘func’ from incompatible pointer type [enabled by default]
   func(p);
   ^
c.c:3:6: note: expected ‘int **’ but argument is of type ‘int *’
 void func(int **p) {
      ^
c.c:12:3: warning: passing argument 1 of ‘func’ from incompatible pointer type [enabled by default]
   func(&pp);
   ^
c.c:3:6: note: expected ‘int **’ but argument is of type ‘int ***’
 void func(int **p) {
      ^

I don't know why ideone doesn't complain about it (http://ideone.com/uzeXur).

over 4 years ago · Santiago Trujillo Report

0

The compiler apparently has no warnings enabled:

int main()
{
    int *p = 0, **p2 = p;

...

$ gcc -std=c11 test.c -lncurses
test.c: In function ‘main’:
test.c:8:21: warning: initialization from incompatible pointer type [enabled by default]
  int *p = 0, **p2 = p;
                     ^

So, gcc complains very well. That site might have disabled warnings or swallows it. It should do neither.

For gcc, You can also turn all warnings to errors with -Werror or just some specific: -Werror=<name of warning>. For this, it would be strict-aliasing.

Reason this is not default is propably historical reasons. Making it an error by default might break too much legacy or otherwise broken software in the wild.

The reason it does not produce an error might be found here in the standard. Sentence 7. It is only UB if the pointer is not properly aligned for the receiving pointer or dereferenced (which is not done here).

over 4 years ago · Santiago Trujillo Report

0

I think ideone is just soft on the warnings. Without -Wall or any extra warning flags on my computer gcc gives me

test_ptrs.c: In function ‘func’:
test_ptrs.c:4:3: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘int **’ [-Wformat=]
   printf("Pointer is at %x\n", p);
   ^
test_ptrs.c: In function ‘main’:
test_ptrs.c:9:3: warning: passing argument 1 of ‘func’ from incompatible pointer type [enabled by default]
   func(p);
   ^
test_ptrs.c:3:6: note: expected ‘int **’ but argument is of type ‘int *’
 void func(int **p) {
      ^
test_ptrs.c:12:3: warning: passing argument 1 of ‘func’ from incompatible pointer type [enabled by default]
   func(&pp);
   ^
test_ptrs.c:3:6: note: expected ‘int **’ but argument is of type ‘int ***’
 void func(int **p) {
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!