¿Cuándo puedo omitir las llaves en C?

8 minutos de lectura

avatar de usuario
ucarión

Estoy casi seguro de que esto se ha preguntado antes, pero no puedo encontrar que se responda en ninguna parte.

¿Cuándo puedo omitir las llaves en C? he visto sin aparatos ortopédicos return declaraciones anteriores, tales como

if (condition)
  return 5;

Pero esto no siempre parece funcionar para todas las declaraciones, es decir, cuando se declara un método.

editar:

¿Las reglas para la omisión de llaves son las mismas que en Java?

  • Bueno, funciona cada vez que el lenguaje espera un “estamento o bloque”…

    – KerrekSB

    15 de febrero de 2013 a las 19:27

  • El código de tu pregunta está bien. Intenta mostrarnos algo que no entiendas.

    –David Heffernan

    15 de febrero de 2013 a las 19:27

  • Es muy buena idea poner esos frenos aunque no sean necesarios en ese preciso momento. Las personas agregan código y tenerlos hace que sea menos probable que el código adicional se coloque en el lugar correcto. ¿Cuál es el daño de presionar algunos botones adicionales? ¡Mucho más fácil que un viernes por la tarde tratando de descubrir por qué un poco de código no funciona como se esperaba!

    – Ed Heal

    15 de febrero de 2013 a las 19:28


  • @EdHeal Tengo que estar de acuerdo, de todo corazón. No puedo pensar en una sola situación en la que sea mejor omitir las llaves

    – Dan F.

    15 de febrero de 2013 a las 19:33

  • Por “declarar un método”, creo que te refieres a “definir una función”.

    –Keith Thompson

    15/02/2013 a las 19:50

avatar de usuario
Juan Bode

Los únicos lugares donde puede omitir los corchetes son para los cuerpos de if-else, for, whileo do-while declaraciones si el cuerpo consta de una sola declaración:

if (cond)
  do_something();

for (;;)
  do_something();

while(condition)
  do_something();

do 
  do_something();
while(condition);

Sin embargo, tenga en cuenta que cada uno de los ejemplos anteriores cuenta como una declaración única de acuerdo con la gramática; eso significa que puedes escribir algo como

if (cond1)
  if (cond2)
    do_something();

Esto es perfectamente legal; if (cond2) do_something(); se reduce a una sola afirmación. Entonces, para el caso, ¿no if (cond1) if (cond2) do_something();por lo que podrías descender más a la locura con algo como

for (i=0; i < N; i++)
  if (cond1)
    if (cond2)
      while (cond3)
        for (j=0; j < M; j++)
          do_something(); 

No hagas eso.

avatar de usuario
keith thompson

Si observa la sintaxis de C, hay una serie de contextos que requieren una declaraciónun término que está definido por la propia gramática.

En cualquiera de esos contextos, una de las formas de declaración que puede usar es un declaración compuestaque consiste en una llave de apertura {una secuencia de cero o más declaraciones y/o sentencias, y una llave de cierre }. (En C90, todas las declaraciones en una declaración compuesta deben preceder a todas las declaraciones; C99 eliminó esa restricción).

A definición de función requiere específicamente un declaración compuesta, no cualquier tipo de declaración. (Estoy bastante seguro de que ese es el único caso en el que una declaración compuesta es el único tipo de declaración que puede usar). Si no fuera por esa restricción, podrías escribir:

void say_hello(void) printf("Hello, world\n");

Pero dado que la mayoría de las definiciones de funciones contienen múltiples declaraciones y/o sentencias, no habría mucha ventaja en permitir eso.

Hay una pregunta aparte: cuando deberían omites las llaves. En mi opinión personal, la respuesta es “casi nunca”. Esta:

if (condition)
     statement;

es perfectamente legal, pero esto:

if (condition) {
    statement;
}

En mi humilde opinión, se lee mejor y es más fácil de mantener (si quiero agregar una segunda declaración, las llaves ya están ahí). Es un hábito que adquirí de Perl, que requiere llaves en todos estos casos.

La única vez que omitiré las llaves es cuando una instrucción if completa o algo similar quepa en una sola línea y, al hacerlo, el código sea más fácil de leer. y Es poco probable que quiera agregar más declaraciones a cada if:

if (cond1) puts("cond1");
if (cond2) puts("cond2");
if (cond3) puts("cond3");
/* ... */

Encuentro que estos casos son bastante raros. E incluso entonces, todavía consideraría agregar las llaves de todos modos:

if (cond1) { puts("cond1"); }
if (cond2) { puts("cond2"); }
if (cond3) { puts("cond3"); }
/* ... */

  • +1, como nota al margen, algunos estándares de codificación siempre requieren el {} para todas las sentencias de iteración (if, for, etc.) incluso si solo hay una declaración. MISRA-C es un ejemplo.

    – ouah

    15 de febrero de 2013 a las 20:23

  • ¡Con razón! Tener frenos ya colocados significa (a) que no tiene que recordarlos más tarde, (b) no corre el riesgo de resultados catastróficos si se olvida de recordarlos más tarde (lo que presumiblemente es una gran parte del ángulo de MISRA), y (c ) su VCS no está inundado de ruido diferencial si su estilo de codificación dice que no debe usar llaves cuando sea ‘innecesario’, las coloca en la misma línea que la instrucción inicial y va entre cuerpos de una o varias líneas (y recuerde añadir/quitar llaves…)

    – subrayado_d

    12/09/2018 a las 11:34

Pero esto no siempre parece funcionar para todas las declaraciones.

¿Específicamente? Cuando se espera una sola declaración, entonces es perfectamente válida. bucles, el if declaración, etc. todos esperan una declaración y eso es un bloque o, bueno, una sola declaración sin estar encerrada en un bloque.

Un ejemplo:

int a[2][2] = {{1, 2}, {3, 4}};

puede utilizar la forma equivalente válida:

int a[2][2] = {1, 2, 3, 4};

Algunos compiladores detallados pueden advertir, pero es válido.

Tenga en cuenta que para el if declaración (lo mismo para el whilelos for declaración, …) la {} no se omiten. Simplemente no se solicitan. los if declaración tiene esta sintaxis:

if (expression) statement

Si desea una declaración múltiple en lugar de una declaración única, puede usar una declaración compuesta que está rodeada {}.

Principalmente necesita llaves cuando desea combinar varias declaraciones o expresiones en una sola, por ejemplo:

{
  x = 1;
  y = 2;
}

Entonces, si pones lo anterior debajo if o else todo lo que está entre llaves se ejecutará como un todo, mientras que si omite las llaves, solo la primera (x = 1; en este caso) se utilizará como parte de if o else.

Típicamente también los usa con switch():

switch (x)
{
case 1:
  // do smth
  break;
case 2:
  // do smth else
  break;
}

Por lo general, los necesita con el do-while declaración:

do
{
  printf("%d\n", x);
  x++;
} while (x < 10);

Los necesita con los compiladores C89 cuando desea definir y usar una variable temporal en medio del código:

int main(void)
{
  puts("Hello World!");
  {
    int x;
    for (x = 0; x < 10; x++)
      printf("%d\n", x);
  }
  return 0;
}

Los usa para comenzar y finalizar el cuerpo de una función, una definición de estructura/unión, una definición de enumeración, la inicialización de una estructura/unión/matriz, por ejemplo:

void blah(void)
{
}

enum e
{
  e1 = 1,
  e2 = 2
};

struct s
{
  int foo;
  int bar;
} s = { 1, 2 };

int a[3] = { 1, 2, 3 };

Puede omitirlos a veces en las inicializaciones, por ejemplo:

char str2[] = { "abc" };
char str1[] = "abc";

  • Sí, también es válido. Pero en cuanto al ejemplo del literal de cadena, no es que se puedan omitir las llaves, sino que el inicializador se puede rodear opcionalmente con {} en estos casos particulares..

    – ouah

    15 de febrero de 2013 a las 19:47


avatar de usuario
dan

Cada vez que hay un bloque con más de una línea (contando las líneas como una sola declaración con ; )

Ejemplos:

for (i = 0; i < j; i++ ) 
   foo(i);

while (1) 
   foo();

if( bool )
   foo();

void cheese()
   printf("CHEESE");

Todo después del ; en las líneas anteriores no cuenta como ‘dentro’ del bloque como si hubiera { }.

  • Sí, también es válido. Pero en cuanto al ejemplo del literal de cadena, no es que se puedan omitir las llaves, sino que el inicializador se puede rodear opcionalmente con {} en estos casos particulares..

    – ouah

    15 de febrero de 2013 a las 19:47


Puede omitirlos cuando hay una sola declaración que está ejecutando:

for(...)
 printf("brackets can be omited here");

if(...)
 printf("brackets can be omited here");
else
 printf("brackets can be omited here too");

etc. Siempre puede agregarlos, nunca duele y ayudar a aclarar el alcance, pero está bastante seguro. El único “trampa” en el que puedo pensar es si intenta hacer una declaración en ese ámbito (lo cual es inútil por cierto):

if(...)
  int a = 5;

Esto provocará un error, pero eso se debe a que puede realizar una sola declaración sin corchetes, no es un declaración. Distinción importante.

Técnicamente hablando, incluso puedes hacer más de una operación sin corchetes si están concatenados con el , operator… no es que aconseje hacerlo, solo digno de mención:

if(...)
    value++, printf("updated value with brackets");

Y a su edición, se puede ver en el especificación java que las reglas son las mismas. Me vinculé específicamente a la if sección, pero se puede ver después de la if se espera una declaración, por lo que puede omitir los corchetes.

¿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