tutorial smart programar para introduccion inteligentes español ejemplos contratos aprender c pointers casting void

c - smart - solidity español



¿Cuándo es necesario lanzar puntero vacío en C? (5)

Creo que el mismo código ha sido referenced en otras questions .

La respuesta en el segundo enlace explica:

No es valido Simplemente funciona si sizeof (int) == sizeof (void *), lo que sucede en muchos sistemas.

Solo se garantiza que un vacío * sea capaz de contener punteros a objetos de datos.

Aquí hay una C Preguntas frecuentes sobre el tema.

Y el texto citado:

¿Cómo se convierten los enteros hacia y desde los punteros? ¿Puedo rellenar temporalmente un entero en un puntero, o viceversa?

Las conversiones de puntero a entero y de entero a puntero están definidas por la implementación (consulte la pregunta 11.33), y ya no hay ninguna garantía de que los punteros se puedan convertir a enteros y viceversa, sin cambio

Forzar punteros en enteros, o enteros en punteros, nunca ha sido una buena práctica

He estado buscando en la programación avanzada de Linux por Mitchell, Oldham y Samuel. He visto en la sección de pthreads algo sobre punteros de vacíos y el casting que me confunde.

Al pasar un argumento a pthread_create (), no lanzan el puntero a un puntero de vacío aunque eso es lo que la función espera.

pthread_create( &thread, NULL, &compute_prime, &which_prime );

Aquí, which_prime es de tipo int .

Pero tomando un valor devuelto desde el hilo usando pthread_join, HACEN la variable para anular el puntero.

pthread_join( thread, (void*) &prime );

Aquí, prime es de tipo int otra vez.

¿Por qué el casting se realiza en segunda instancia y no en la primera?


El segundo ejemplo es un buen ejemplo de por qué el hecho de lanzar para void* suele ser un error. Debería ser

void *primep = ′ // no cast needed pthread_join(thread, &primep);

porque pthread_join toma un void** como su segundo argumento. El void* solo se asegura de que el error pase el compilador porque el void* se convierte en void** automáticamente.

Entonces, ¿cuándo necesitas lanzar para void* o volver?

  • cuando se trabaja con punteros almacenados como enteros ( (u)intptr_t );
  • cuando se pasan punteros a funciones que tienen un prototipo incompleto y se void* (o se toma un tipo de puntero diferente y se void* ); eso generalmente significa que las funciones toman una cantidad variable de argumentos, como printf .

En C, la conversión al vacío * desde cualquier tipo de puntero y viceversa se realiza de manera implícita. No hay necesidad para el elenco en el segundo ejemplo.

(Tenga en cuenta que en C ++ la conversión de cualquier puntero a void * también se realiza de manera implícita (excepto para los punteros de función y los punteros de función / miembro / método que no se pueden convertir a void *), pero la conversión de vuelta requiere una conversión explícita.


No es necesario lanzar desde o hacia un puntero para void en C:

6.3.2.3 Punteros

1 Un puntero para anular se puede convertir en un puntero a cualquier tipo de objeto incompleto o desde un puntero. Un puntero a cualquier tipo de objeto o incompleto se puede convertir en un puntero para anular y viceversa; El resultado se comparará igual al puntero original.

Las únicas excepciones a esto son

  • al imprimir un puntero utilizando el especificador de conversión "%p" ya que solo está definido para void * .
  • al copiar el valor de un puntero desde un intptr_t o uintptr_t nuevo a un void * .

Según la documentation,

int pthread_join(pthread_t thread, void **retval);

Por lo tanto, pthread_join toma un pointer to void* como su segundo argumento. Esto es porque,

En pthread_join, recuperas la dirección pasada a pthread_exit por el hilo terminado. Si pasa solo un puntero plano, se pasa por valor para que no pueda cambiar hacia donde apunta. Para poder cambiar el valor del puntero pasado a pthread_join, se debe pasar como un puntero en sí, es decir, un puntero a un puntero.

Ahora, a su pregunta, " ¿Por qué el casting se realiza en la segunda instancia y no en la primera? " En la primera instancia, es decir, pthread_create , se espera un void* como su cuarto argumento. Así, pasar &which_prime se convertiría implícitamente a void* .

En la segunda instancia, es decir, pthread_join , espera un void** y estamos pasando &prime allí. Así, el compilador se quejará. Por lo tanto, para evitar el error, el autor pasa un molde de void* que se convertirá automáticamente en void** .

Pero esta no es una buena solución.

La solución::

void* prime ; // make prime as void* pthread_join( thread, &prime ); printf( "%" PRIxPTR "/n", (intptr_t)prime ) ; // intptr_t instead of int to get an integer type // that''s the same size as a pointer