Buscar..


Impresión del valor de un puntero a un objeto

Para imprimir el valor de un puntero a un objeto (en lugar de un puntero de función) use el especificador de conversión p . Se define para imprimir solo los puntos de void , por lo que para imprimir el valor de un punto de no void se debe convertir explícitamente ("fundido *") a void* .

#include <stdlib.h> /* for EXIT_SUCCESS */
#include <stdio.h>  /* for printf() */

int main(void)
{
  int i;
  int * p = &i;

  printf("The address of i is %p.\n", (void*) p);

  return EXIT_SUCCESS;
}
C99

Usando <inttypes.h> y uintptr_t

Otra forma de imprimir punteros en C99 o posterior utiliza el tipo uintptr_t y las macros de <inttypes.h> :

#include <inttypes.h> /* for uintptr_t and PRIXPTR */
#include <stdio.h>    /* for printf() */

int main(void)
{
  int  i;
  int *p = &i;

  printf("The address of i is 0x%" PRIXPTR ".\n", (uintptr_t)p);

  return 0;
}

En teoría, es posible que no haya un tipo de entero que pueda contener cualquier puntero convertido en un entero (por lo que el tipo uintptr_t puede no existir). En la práctica, sí existe. Los punteros a las funciones no necesitan ser convertibles al tipo uintptr_t , aunque nuevamente son convertibles.

Si el tipo uintptr_t existe, también lo hace el tipo intptr_t . Sin embargo, no está claro por qué querría tratar las direcciones como enteros con signo.

K&R C89

Historia Pre-Estándar:

Antes de C89 durante los tiempos K y R-C, no había ningún tipo void* (ni encabezado <stdlib.h> , ni prototipos, y por lo tanto no había una notación int main(void) ), por lo que el puntero se proyectó a long unsigned int y se imprimió utilizando lx modificador de longitud / especificador de conversión.

El siguiente ejemplo es sólo para fines informativos. Hoy en día este código no es válido, lo que muy bien podría provocar el infame comportamiento indefinido .

#include <stdio.h> /* optional in pre-standard C - for printf() */

int main()
{
  int  i;
  int *p = &i;

  printf("The address of i is 0x%lx.\n", (long unsigned) p);

  return 0;
}

Impresión de la diferencia de los valores de dos punteros a un objeto

Restar los valores de dos punteros a un objeto da como resultado un entero con signo * 1 . Por lo tanto, se imprimiría utilizando al menos el especificador de conversión d .

Para asegurarse de que hay un tipo lo suficientemente ancho como para contener tal "diferencia de puntero", ya que C99 <stddef.h> define el tipo ptrdiff_t . Para imprimir un ptrdiff_t usa el modificador t longitud.

C99
#include <stdlib.h> /* for EXIT_SUCCESS */
#include <stdio.h> /* for printf() */
#include <stddef.h> /* for ptrdiff_t */


int main(void)
{
  int a[2];
  int * p1 = &a[0], * p2 = &a[1];
  ptrdiff_t pd = p2 - p1;

  printf("p1 = %p\n", (void*) p1);
  printf("p2 = %p\n", (void*) p2);
  printf("p2 - p1 = %td\n", pd);

  return EXIT_SUCCESS;
}

El resultado podría verse así:

p1 = 0x7fff6679f430
p2 = 0x7fff6679f434
p2 - p1 = 1

Tenga en cuenta que el valor resultante de la diferencia se escala según el tamaño del tipo al que los punteros le restaron el punto, un int aquí. El tamaño de un int para este ejemplo es 4.


* 1 Si los dos punteros que se deben restar no apuntan al mismo objeto, el comportamiento no está definido.

Especificadores de conversión para la impresión

Especificador de conversión Tipo de argumento Descripción
i , d En t imprime decimal
u sin firmar int imprime decimal
o sin firmar int impresiones octales
x sin firmar int Impresiones hexadecimales, minúsculas.
X sin firmar int impresiones hexadecimales, mayúsculas
f doble las impresiones flotan con una precisión predeterminada de 6, si no se proporciona ninguna precisión (minúscula utilizada para números especiales nan e inf o infinity )
F doble las impresiones flotan con una precisión predeterminada de 6, si no se proporciona ninguna precisión (mayúscula utilizada para los números especiales NAN e INF o INFINITY )
e doble las impresiones flotan con una precisión predeterminada de 6, si no se da una precisión, usando notación científica usando mantisa / exponente; Exponente en minúsculas y números especiales.
E doble las impresiones flotan con una precisión predeterminada de 6, si no se da una precisión, usando notación científica usando mantisa / exponente; Exponente en mayúsculas y números especiales.
g doble utiliza f o e [ver más abajo]
G doble utiliza F o E [ver más abajo]
a doble Impresiones hexadecimales, minúsculas.
A doble impresiones hexadecimales, mayúsculas
c carbonizarse imprime un solo carácter
s carbonizarse* imprime una cadena de caracteres hasta un terminador NUL , o truncada a la longitud dada por la precisión, si se especifica
p vacío* imprime el void puntero void ; un punto no void debe convertirse explícitamente ("cast") a void* ; puntero a objeto solamente, no un puntero a función
% n / A imprime el carácter %
n En t * escriba el número de bytes impresos hasta el momento en el int apuntado.

Tenga en cuenta que los modificadores de longitud se pueden aplicar a %n (por ejemplo, %hhn indica que el siguiente especificador de conversión n aplica a un puntero a un argumento signed char , según ISO / IEC 9899: 2011 §7.21.6.1 (7)).

Tenga en cuenta que las conversiones de punto flotante se aplican a los tipos float y double debido a las reglas de promoción predeterminadas - §6.5.2.2 Llamadas de función, ¶7 La notación de puntos suspensivos en un declarador de prototipo de función hace que la conversión de tipo de argumento se detenga después del último parámetro declarado. Las promociones de argumentos predeterminados se realizan en los argumentos finales. ) Por lo tanto, funciones como printf() solo pasan valores double , incluso si la variable referenciada es de tipo float .

Con los formatos g y G , la elección entre la notación e y f (o E y F ) está documentada en el estándar C y en la especificación POSIX para printf() :

El doble argumento que representa un número de punto flotante se convertirá en el estilo f o e (o en el estilo F o E en el caso de un especificador de conversión G ), dependiendo del valor convertido y la precisión. Sea P igual a la precisión si no es cero, 6 si se omite la precisión o 1 si la precisión es cero. Entonces, si una conversión con estilo E tendría un exponente de X :

  • Si P> X> = -4, la conversión será con estilo f (o F ) y precisión P - (X+1) .
  • De lo contrario, la conversión será con estilo e (o E ) y precisión P - 1 .

Finalmente, a menos que se use la bandera '#', los ceros finales se eliminarán de la parte fraccionaria del resultado y el carácter de punto decimal se eliminará si no queda parte fraccionaria.

La función printf ()

Se accede a través de la inclusión de <stdio.h> , la función printf() es la herramienta principal utilizada para imprimir texto en la consola en C.

printf("Hello world!");
// Hello world!

Los arreglos de caracteres normales y sin formato se pueden imprimir solos colocándolos directamente entre los paréntesis.

printf("%d is the answer to life, the universe, and everything.", 42);
// 42 is the answer to life, the universe, and everything.

int x = 3;
char y = 'Z';
char* z = "Example";
printf("Int: %d, Char: %c, String: %s", x, y, z);
// Int: 3, Char: Z, String: Example

Alternativamente, los enteros, los números de punto flotante, los caracteres y más pueden imprimirse usando el carácter de escape % , seguido de un carácter o secuencia de caracteres que denotan el formato, conocido como el especificador de formato .

Todos los argumentos adicionales a la función printf() están separados por comas, y estos argumentos deben estar en el mismo orden que los especificadores de formato. Los argumentos adicionales se ignoran, mientras que los argumentos escritos incorrectamente o la falta de argumentos causarán errores o comportamiento indefinido. Cada argumento puede ser un valor literal o una variable.

Después de la ejecución exitosa, la cantidad de caracteres impresos se devuelve con el tipo int . De lo contrario, un fallo devuelve un valor negativo.

Modificadores de longitud

Los estándares C99 y C11 especifican los siguientes modificadores de longitud para printf() ; sus significados son:

Modificador Modifica Se aplica a
S.S d, i, o, u, x, o x char , signed char o unsigned char
h d, i, o, u, x, o x short int o unsigned short int
l d, i, o, u, x, o x long int o unsigned long int
l a, A, e, E, f, F, g, o G double (para compatibilidad con scanf() ; indefinido en C90)
ll d, i, o, u, x, o x long long int o unsigned long long int
j d, i, o, u, x, o x intmax_t o uintmax_t
z d, i, o, u, x, o x size_t o el tipo firmado correspondiente ( ssize_t en POSIX)
t d, i, o, u, x, o x ptrdiff_t o el tipo entero sin signo correspondiente
L a, A, e, E, f, F, g, o G long double

Si aparece un modificador de longitud con cualquier especificador de conversión distinto al especificado anteriormente, el comportamiento no está definido.

Microsoft especifica algunos modificadores de longitud diferentes y explícitamente no admite hh , j , z o t .

Modificador Modifica Se aplica a
I32 d, i, o, x, o x __int32
I32 o, u, x, o x unsigned __int32
I64 d, i, o, x, o x __int64
I64 o, u, x, o x unsigned __int64
yo d, i, o, x, o x ptrdiff_t (es decir, __int32 en plataformas de 32 bits, __int64 en plataformas de 64 bits)
yo o, u, x, o x size_t (es decir, unsigned __int32 en plataformas de 32 bits, unsigned __int64 en plataformas de 64 bits)
l o l a, A, e, E, f, g, o G long double (en Visual C ++, aunque el long double es un tipo distinto, tiene la misma representación interna que el double ).
l o w c o c Carácter ancho con funciones printf y wprintf . (Un especificador de tipo lc , lC , wc o wC es sinónimo de C en las funciones de printf y de c en wprintf funciones de wprintf ).
l o w s, s o z Cadena de caracteres wprintf funciones printf y wprintf . (Un especificador de tipo ls , lS , ws o wS es sinónimo de S en las funciones de printf y de s en wprintf funciones de wprintf ).

Tenga en cuenta que el C , S , y Z especificadores de conversión y la I , I32 , I64 , y w modificadores de longitud son extensiones de Microsoft. Tratar a l como un modificador para el long double lugar de double es diferente del estándar, aunque será difícil encontrar la diferencia a menos que el long double tenga una representación diferente del double .

Formato de impresión de banderas

El estándar C (C11 y C99 también) define los siguientes indicadores para printf() :

Bandera Conversiones Sentido
- todos El resultado de la conversión se justificará a la izquierda dentro del campo. La conversión está justificada a la derecha si no se especifica este indicador.
+ numérico firmado El resultado de una conversión firmada siempre comenzará con un signo ('+' o '-'). La conversión comenzará con un signo solo cuando se convierta un valor negativo si no se especifica este indicador.
<space> numérico firmado Si el primer carácter de una conversión firmada no es un signo o si una conversión firmada no produce ningún carácter, se colocará un prefijo <space> sobre el resultado. Esto significa que si los indicadores <space> y ' + ' aparecen ambos, el indicador <space> se ignorará.
# todos Especifica que el valor se convertirá a una forma alternativa. Para la conversión o , aumentará la precisión, si y solo si es necesario, para forzar que el primer dígito del resultado sea cero (si el valor y la precisión son ambos 0, se imprime un solo 0). Para los especificadores de conversión x o X , un resultado distinto de cero tendrá 0x (o 0X ) prefijados. Para los especificadores de conversión a , A , e , E , f , F , g y G , el resultado siempre contendrá un carácter de raíz, incluso si ningún dígito sigue al carácter de raíz. Sin este indicador, un carácter de raíz aparece en el resultado de estas conversiones solo si un dígito lo sigue. Para los especificadores de conversión g y G , los ceros finales no se eliminarán del resultado como lo son normalmente. Para otros especificadores de conversión, el comportamiento no está definido.
0 numérico Para los especificadores de conversión d, i, o, u, x, X, a, A, e, E, f, F, g y G, se utilizan ceros a la izquierda (después de cualquier indicación de signo o base) para rellenar el campo ancho en lugar de realizar relleno de espacio, excepto al convertir un infinito o NaN. Si los indicadores '0' y '-' aparecen ambos, el indicador '0' se ignora. Para los especificadores de conversión d, i, o, u, xy X, si se especifica una precisión, se ignorará el indicador '0'. ⌦ Si aparecen los indicadores '0' y <apostrophe> , los caracteres de agrupación se insertan antes del relleno cero. Para otras conversiones, el comportamiento es indefinido. ⌫

Microsoft también admite estos indicadores con los mismos significados.

La especificación POSIX para printf() agrega:

Bandera Conversiones Sentido
' i, d, u, f, F, g, G La parte entera del resultado de una conversión decimal se formateará con miles de caracteres de agrupación. Para otras conversiones el comportamiento es indefinido. Se utiliza el carácter de agrupación no monetaria.


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow