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

275
Views
¿Por qué el puntero implícito de la conversión de puntero a puntero es legal?

Recientemente encontré un código en stackoverflow donde los punteros a los punteros se usaban para cambiar la memoria asignada. Mientras revisaba el código, cometí el error de agregar un ampersand a un puntero, así que haga un puntero a un puntero, pero el compilador compiló felizmente y se produjeron errores de tiempo de ejecución. Como ejemplo

 #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; }

Entiendo que C tiene restricciones significativamente más bajas para punteros que C++ y permite algo como char *buf = malloc(SIZE) mientras que C++ no está permitido. Lo veo como una conveniencia porque sucede mucho en C.

Sin embargo, creo que la cantidad de referencias es una gran fuente de errores y me pregunto por qué se podría permitir esto, especialmente porque int es diferente de int* . Además, quiero saber si el estándar C dice algo al respecto.

EDITAR Lo compilé en ideone.com, que probablemente no muestre advertencias. Mi compilador clang local, así como gcc, dan advertencias. Aún así, ¿por qué son solo advertencias cuando representan cosas diferentes?


PD: Siento que algo como esto debería haberse preguntado en los últimos seis años de SO. Si se trata de un duplicado, lo siento por no encontrar uno.

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

La conversión no es legal. Más precisamente, no hay una conversión implícita de int* a int** , o de int*** a int** . Intentar pasar un int* o un int*** a una función que requiere un argumento int** es una violación de restricción ; cualquier compilador conforme debe diagnosticarlo. (El mensaje de diagnóstico puede ser una advertencia no fatal).

Cuando compilo su código con gcc, incluso con las opciones predeterminadas (lo que hace que gcc no cumpla), recibo varias advertencias:

 cc: In function 'func': cc: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); ^ cc: In function 'main': cc:9:3: warning: passing argument 1 of 'func' from incompatible pointer type [enabled by default] func(p); ^ cc:3:6: note: expected 'int **' but argument is of type 'int *' void func(int **p) { ^ cc:12:3: warning: passing argument 1 of 'func' from incompatible pointer type [enabled by default] func(&pp); ^ cc:3:6: note: expected 'int **' but argument is of type 'int ***' void func(int **p) { ^

No sé por qué ideone no se queja ( http://ideone.com/uzeXur ).

over 4 years ago · Santiago Trujillo Report

0

El compilador aparentemente no tiene advertencias habilitadas:

 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; ^

Entonces, gcc se queja muy bien. Ese sitio podría haber deshabilitado las advertencias o se lo traga. No debería hacer nada.

Para gcc, también puede convertir todas las advertencias en errores con -Werror o simplemente algunos específicos: -Werror=<name of warning> . Para esto, sería strict-aliasing .

La razón por la que esto no es predeterminado es probablemente por razones históricas. Hacer que sea un error de forma predeterminada podría romper demasiado software heredado o roto en la naturaleza.

La razón por la que no produce un error se puede encontrar aquí en el estándar . Oración 7. Solo es UB si el puntero no está correctamente alineado para el puntero de recepción o no está referenciado (lo que no se hace aquí).

over 4 years ago · Santiago Trujillo Report

0

Creo que ideone es suave con las advertencias. Sin -Wall o cualquier indicador de advertencia adicional en mi computadora, gcc me da

 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!