usar _ y __ en programas C [duplicate]

9 minutos de lectura

Estaba leyendo el libro de K&R. Yo leo:

… el nombre destinado a ser utilizado solo por las funciones de la biblioteca estándar comienza con _ por lo que es menos probable que colisionen con los nombres en el programa de usuario…

¿Qué significa esto exactamente? Explíquelo de una manera realmente simple y práctica.

Lo que entendí es:

si quiero usar sqrt definido en math.h entonces

#include <math.h>
#define sqrt(x) x*x*x

main() 
{ 
int x=4; 
_sqrt(x); // That is from the header file math.h
sqrt(x); // my own defined macro 
/*or its the reverse way _sqrt for my own defined macro so it won't collide with original sqrt i.e. without _ for sqrt from math.h */ 
return 0;
}

Ahora, leo un código en stackoverflow usando __. sys/syscall.h no está presente en Windows, por lo que debemos usar

#if __linux 
#include <sys/syscall.h>
#elif defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#endif

donde esta exactamente __ usado y cuál es la diferencia b/w __ & _. Ingresa el código aquí

  • Creo que algunos de ellos también están reservados para el compilador.

    – OMGtechy

    2 de agosto de 2014 a las 1:03

  • “explicar de manera sencilla y práctica real”. – No empieces los nombres de tus cosas con _ o __.

    – usuario229044

    2 de agosto de 2014 a las 1:04


  • Exactamente lo que dijo @meagar. A menos que esté escribiendo su propio compilador o libc, o realmente quiera jugar a ser abogado de idiomas, simplemente no nombre nada con un guión bajo al principio y estará bien.

    – R.. GitHub DEJA DE AYUDAR A ICE

    2 de agosto de 2014 a las 1:31

  • Hay muchos duplicados posibles, que incluyen: Significado de notaciones como _NAME, _NAME_, __NAME, __NAME__ y Formato de nombre de variable comúnmente aceptado en C/C++ y Comprensión de las convenciones de origen de glibc e incluso ¿Qué significa __const media en C, etc.

    –Jonathan Leffler

    2 de agosto de 2014 a las 1:31


Esto es lo que el estándar c dice (sección 7.1.3):

  • Todos los identificadores que comienzan con un guión bajo y una letra mayúscula u otro guión bajo siempre están reservados para cualquier uso.
  • Todos los identificadores que comienzan con un guión bajo siempre se reservan para su uso como identificadores con ámbito de archivo en los espacios de nombres ordinarios y de etiquetas.

(La sección continúa con una lista de identificadores específicos y conjuntos de identificadores reservados por ciertos encabezados estándar).

Lo que esto significa es que, por ejemplo, la implementación (ya sea el compilador o un encabezado estándar) puede usar el nombre __FOO por cualquier cosa que le guste. Si define ese identificador en su propio código, el comportamiento de su programa no está definido. Si tiene “suerte”, utilizará una implementación que no la define, y su programa funcionará como se esperaba.

Esto significa que simplemente no debe definir ningún identificador de este tipo en su propio código (a menos que su propio código sea parte de una implementación de C, y si tiene que preguntar, no lo es). No hay necesidad de definir dichos identificadores de todos modos; casi no hay escasez de identificadores no reservados.

Puedes usar un identificador como _foo siempre que se defina localmente (no en el alcance del archivo), pero personalmente me resulta mucho más fácil evitar el uso de guiones bajos al principio.

Por cierto, su ejemplo de _sqrt no ilustra necesariamente el punto. Una implementación mayo definir el nombre _sqrt en <math.h> (ya que todo lo definido allí está en el alcance del archivo), pero no hay una razón particular para esperar que lo haga. Cuando compilo su programa, recibo una advertencia:

c.c:7:1: warning: implicit declaration of function ‘_sqrt’ [-Wimplicit-function-declaration]

porque <math.h> en mi sistema no defina ese identificador y un error fatal en el tiempo de enlace:

/tmp/cc1ixRmL.o: In function `main':
c.c:(.text+0x1a): undefined reference to `_sqrt'

porque no hay tal símbolo en la biblioteca.

  • ¿Este consejo (de no usar _ seguido de un carácter alfabético en minúsculas en el ámbito del archivo) se aplican a estático funciones, es decir, con enlace interno? Supongo que dado que tienen alcance de archivo, lo hace. ¿Existe una convención de nomenclatura popular para funciones estáticas que se pueda usar (y, por lo tanto, reconocer comúnmente) en su lugar? Prefijo mis nombres de funciones públicas con el nombre del módulo (p. ej. foo_sqrt()), así que supongo que al menos mis funciones estáticas podrían no tener el foo_ prefijo.

    – davidA

    23 de abril de 2020 a las 2:03


  • Sí, las funciones estáticas de alcance de archivo siguen siendo de alcance de archivo, por lo que los nombres que comienzan con _ aún se conservan en ese contexto. Realmente, lo más fácil de hacer es simplemente Nunca declarar algo con un nombre que comience con _ (a menos que esté escribiendo parte de la implementación). No uses el nombre sqrtya que <math.h> podría definirlo como una macro. De manera más general, no reutilizaría ningún nombre definido por la biblioteca estándar, simplemente para evitar confusiones, incluso si está en un contexto seguro. (Por ejemplo, no llame a una función de registro logya que ese es el nombre de la función de logaritmo natural).

    –Keith Thompson

    23 de abril de 2020 a las 3:20

avatar de usuario
usuario2485710

Es una convención de nomenclatura, esto significa que violar esta regla no conducirá de manera inmediata y directa a romper su programa, pero es realmente realmente realmente realmente realmente [ + infinite times ] una buena idea seguir la convención.

La esencia de la convención es reservar:

  • nombrar comenzando con _ para las entidades de lenguaje, que incluye la biblioteca estándar
  • nombrar comenzando con __ para las partes internas del compilador

también es un tema realmente específico de la plataforma la mayoría de las veces, muchos proveedores respetan esta convención pero también tienen sus propias convenciones y pautas de nomenclatura.

Puedes encontrar más buscando c convención de nomenclatura de doble guión bajo

  • “Entidades de lenguaje” versus “componentes internos del compilador” no es una descripción correcta de la distinción.

    – R.. GitHub DEJA DE AYUDAR A ICE

    2 de agosto de 2014 a las 1:23

  • @R.. Comentarios como este son la razón por la cual el mundo es tan hermoso; Si tiene algo que decir, simplemente dígalo, usted es un programador, usted funciona, simplemente hágalo.

    – usuario2485710

    2 de agosto de 2014 a las 1:26


  • No estoy muy seguro de qué hacer con tu respuesta. Otras respuestas han citado el texto en el estándar sobre cuál es la distinción formal entre _ y __ realmente es. Su respuesta es en gran parte correcta, pero no veo ninguna evidencia que respalde su afirmación sobre cómo se usan para “entidades de lenguaje” versus “componentes internos del compilador”.

    – R.. GitHub DEJA DE AYUDAR A ICE

    2 de agosto de 2014 a las 1:29


  • Una implementación de la biblioteca estándar es libre de definir identificadores que comienzan con __.

    –Keith Thompson

    2 mayo 2016 a las 19:29

  • El implementador de la biblioteca estándar no puede usar libremente nombres que comiencen con _ pero no seguido de otro guión bajo ni de una letra mayúscula. Estos nombres sirven como identificadores internos para el código de usuario. Cualquier implementación de C con static int _foo; en uno de sus sistemas la cabecera está rota; rompe el código de usuario conforme para hacerlo.

    – jdh8

    11/10/2017 a las 17:54

avatar de usuario
slezica

tl; Dr Lo entendiste al revés. Nombra tus propias cosas sin guiones bajos al principio, a menos que estés escribiendo una biblioteca para otra persona. La biblioteca estándar y los compiladores usan la técnica para indicar que ciertos nombres son internos y no deben usarse directamente.

Guiones bajos para singularidad

En C, no hay espacios de nombres. En otras palabras, todos los nombres incluidos en un archivo pueden colisionar entre sí. Si foo.h y bar.h ambos definen xse producirá un error cuando se incluyan ambos.

Ahora, x es un nombre bastante común. La colisión está casi garantizada, y los escritores de foo.h y bar.h debe darse cuenta de eso. Entonces, en aras de evitar futuros problemas a los programadores que usarán su código, cambian el nombre a _x.

Alternativas

Aparecen nombres comunes. Antes de recurrir al subrayado, intente:

  1. Separar las variables privadas de las públicas en .c y .h archivos La mayoría de los nombres en conflicto son privados y no pertenecen al encabezado.

  2. Prefijando su código con el nombre del módulo: foo_x y bar_x no chocará.

  • bibliotecas que no son parte de la implementación de C aún no debería definir identificadores con guiones bajos al principio.

    –Keith Thompson

    2 de agosto de 2014 a las 1:20

  • Hay espacios de nombres en C, pero no los mismos que están en C++ u otros lenguajes. struct foo; y typedef int foo; no colisionan en C debido al espacio de nombres de la etiqueta, pero sí colisionan en C++.

    – sueño relajado

    2 de agosto de 2014 a las 1:23

  • ¿Este consejo (de no usar _) aplicar para estático funciones?

    – davidA

    23 de abril de 2020 a las 2:00

  • No he codificado C por más de 5 años, así que estoy un poco pasado de moda, pero la lógica es la misma: subrayar cosas para indicar que no debe usarse fuera de los límites de la biblioteca y para evitar conflictos con el propios espacios de nombres de la persona que llama. Cuáles son los estándares actuales, ni idea, pero el razonamiento se mantiene.

    – slezica

    23 de abril de 2020 a las 13:59

  • a menos que estés escribiendo una biblioteca para otra persona” tiene que leer “a menos que esté escribiendo la biblioteca estándar“.

    –Toby Speight

    18 de octubre de 2021 a las 7:26

¿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