¿Por qué el tamaño de una función en C siempre es de 1 byte?

6 minutos de lectura

avatar de usuario
usuario1645461

Cuando comprobamos el tamaño de una función usando sizeof()siempre obtenemos 1 byte. ¿Qué significa este 1 byte?

avatar de usuario
Kerrek SB

Es una violación de restricción, y su compilador deberían diagnosticarlo. Si lo compila a pesar de eso, su programa tiene un comportamiento indefinido [thanks to @Steve Jessop for the clarification of the failure mode, and see @Michael Burr’s answer for why some compilers allow this]: Desde C11, 6.5.3.4./1:

los sizeof El operador no se aplicará a una expresión que tenga el tipo de función.

  • Esa es una restricción, lo que significa que en un compilador conforme se diagnostica. Si el compilador lo compila de todos modos (después de haberlo diagnosticado), entonces el comportamiento no está definido. Si el compilador no lo diagnostica (lo que, por ejemplo, gcc no hace sin -pedantic), tiene un compilador no conforme y cada programa tiene un comportamiento indefinido.

    –Steve Jessop

    4 de septiembre de 2012 a las 9:46


  • El comportamiento lo coloca en la misma categoría que una extensión GNU C, pero no tengo idea de por qué alguien quiere ese comportamiento, así que no sé por qué los autores de GNU se tomaron la molestia de agregarlo.

    –Steve Jessop

    4 de septiembre de 2012 a las 9:49


  • @SteveJessop: tenga en cuenta que esto es incluso con -std=c11, no gnu11. Esta es una extensión de compilador realmente extraña.

    – KerrekSB

    4 de septiembre de 2012 a las 9:50

  • ¡Oh! Apuesto a que es para habilitar la aritmética en los punteros de función, de la misma manera que sizeof(void) es 1 en GNU C.

    –Steve Jessop

    4 de septiembre de 2012 a las 9:52


  • Con respecto a -std=c11: alguien debería referir el -std=c* opciones a los estándares publicitarios. No habilitan el modo de conformidad, simplemente deshabilitan las extensiones que impedirían la compilación de un programa bien formado (como typeof siendo una palabra clave, ya que un programa en C bien formado puede usarlo como un nombre de variable, pero gcc por defecto lo rechazaría). Para deshabilitar adicionalmente las extensiones que permiten que los programas mal formados pasen sin ser diagnosticados, necesita -pedantic o -pedantic-errors.

    –Steve Jessop

    4 de septiembre de 2012 a las 9:58


Este no es un comportamiento indefinido: el estándar del lenguaje C requiere un diagnóstico cuando se usa el sizeof operador con un designador de función (un nombre de función) ya que es una violación de restricción para el sizeof operador.

Sin embargo, como una extensión del lenguaje C, GCC permite la aritmética en void punteros y punteros de función, lo que se hace tratando el tamaño de un void o una función como 1. Como consecuencia, el sizeof el operador evaluará a 1 por void o una función con GCC. Ver http://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html#Pointer-Arith

Puede hacer que GCC emita una advertencia al usar sizeof con estos operandos usando el -pedantic o -Wpointer-arith opciones a GCC. O cometer un error con -Werror=pointer-arith.

  • Tu lógica es defectuosa. C requiere mensajes de diagnóstico para algunos, pero no para todos los UB. No puede afirmar que algo tiene un comportamiento definido solo porque hay un diagnóstico.

    – MSalters

    4 de septiembre de 2012 a las 9:05

  • C requiere un diagnóstico para todas las violaciones de restricciones (5.1.1.3 Diagnósticos en C99 o C11). Una restricción (3.8 en C99/C11) es una “restricción, ya sea sintáctica o semántica, mediante la cual se debe interpretar la exposición de los elementos del lenguaje”, lo que parece decir que algo que no sigue las restricciones no se puede interpretar. .

    – Michael Burr

    4 de septiembre de 2012 a las 9:13

  • Y para ser claros, una violación de restricción no da como resultado un comportamiento indefinido. Es un error, como un error de sintaxis. Por ejemplo, la norma dice, “si un requisito de “debe” o “no debe” que aparece fuera de una restricción se viola, el comportamiento no está definido”. Si una violación de la restricción daría como resultado UB, ¿por qué el estándar hablaría solo de los “debe” y “no debe” que no están en restricciones aquí?

    – Michael Burr

    4 de septiembre de 2012 a las 9:27

  • Realmente no dije mucho sobre UB excepto que sizeof una función no es UB (que mencioné prácticamente solo porque otras respuestas indicaron que era UB). Pero tal vez lo confundí por la forma en que estructuré la oración. Para ser más claro. sizeof una función no es UB (como han afirmado varias respuestas). Es una violación de restricción. Como tal, requiere un diagnóstico. GCC lo permite como una extensión.

    – Michael Burr

    4 de septiembre de 2012 a las 9:50

  • @KerrekSB: el OP no obtiene un diagnóstico porque presumiblemente están usando GCC, lo que permite este uso como una extensión del lenguaje C.

    – Michael Burr

    4 de septiembre de 2012 a las 9:52


Significa que el escritor del compilador decidió un valor de 1 en lugar de hacer que los demonios salgan volando de tu nariz (de hecho, fue otro uso indefinido de sizeof que nos dio esa expresión: “el compilador C mismo DEBE emitir un diagnóstico SI este es el primer diagnóstico requerido que resulta de su programa, y ​​luego PUEDE hacer que los demonios salgan volando de su nariz (que, por cierto, bien podría SER el documentado mensaje de diagnóstico) del mismo modo que PUEDE emitir más diagnósticos para futuras violaciones de las reglas o restricciones de sintaxis (o, para el caso, por cualquier motivo que elija).” https://groups.google.com/forum/?fromgroups=#!msg/comp.std.c/ycpVKxTZkgw/S2hHdTbv4d8J

A partir de esto, hay un término de jerga “demonios nasales” para cualquier cosa que un compilador decida hacer en respuesta a una construcción indefinida. 1 es el demonio nasal de este compilador para este caso.

  • @IlmariKaronen Sin embargo, debo admitir que hay una razón por la cual la mayoría de mis respuestas en C (y C ++) se basan en principios generales independientes del lenguaje o pepitas históricas como esa. Mi experiencia C roza lo histórico en sí mismo 🙂

    – Jon Hanna

    4 sep 2012 a las 22:51

Como señalaron otros, sizeof() puede tomar cualquier identificador válido, pero no devolverá un resultado válido (honestamente verdadero y válido) para los nombres de funciones. Además, definitivamente puede, o no, resultar en el síndrome de “demonios fuera de la nariz”.

Si desea perfilar el tamaño de la función de su programa, verifique el mapa del enlazador, que se puede encontrar en el directorio de resultados intermedios (donde se compilan las cosas en .obj/.o o donde se encuentra la imagen/ejecutable resultante). A veces hay una opción para generar o no este archivo de mapa… depende del compilador/enlazador.

Si desea el tamaño de un puntero a una función, todos tienen el mismo tamaño, el tamaño de una palabra de direccionamiento en su CPU.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad