¿Diferencia entre int main () e int main (void)?


¿Qué significa lo siguiente:

int main(void) {...} 

VS

int main() {...}

?

Creo que int main() {...} significa que main no recibe ningún parámetro (desde la línea de comandos) , sin embargo:

int main(int argc, char *argv[])

Lo hace.

Pero ¿qué significa int main(void) {...}? ¿qué significa el vacío ?

He mirado aquí pero de alguna manera es una pregunta diferente .

 54
Author: Community, 2012-09-01

8 answers

En C++, no hay diferencia.


En C, la diferencia es cuestionable. A algunos les encanta argumentar que la última versión (la que no tiene void) es técnicamente solo una extensión de implementación común y no está garantizada para funcionar por el estándar debido a la redacción en el estándar. Sin embargo, el estándar establece claramente que en una definición de función un conjunto vacío de parámetros tiene un comportamiento bien definido: que la función no toma ningún parámetro. Por lo tanto, tal definición para main coincide con la siguiente descripción en el estándar:

It [main] se definirá con un tipo de retorno de int y sin parámetros.

Hay, sin embargo, una diferencia notable entre los dos: a saber, la versión sin void no proporciona un prototipo correcto para la función:

// this is OK.
int main()
{
  if (0) main(42);
}

// this requires a diagnostic to be shown during compiling
int main(void)
{
  if (0) main(42);
}

Oh, y solo para ser completo: el void tiene el siguiente significado en todos los declaradores de funciones:

(6.7.6.3p10) El caso especial de un anónimo parámetro de tipo void como único elemento de la lista especifica que la función no tiene parámetros.

 49
Author: eq-,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-01 05:52:44

En C, en un prototipo (aunque no en C++) una lista de argumentos vacía significa que la función podría tomar cualquier argumentos (en la definición de una función, significa que no hay argumentos). En C++, una lista de parámetros vacía significa que no hay argumentos. En C, para no obtener argumentos, tienes que usar void. Ver esta pregunta para una mejor explicación.

 6
Author: Linuxios,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:50

En C++ tener una función foo(void) y foo() es lo mismo. Sin embargo, en C es diferente: foo(void) es una función que no tiene argumentos, mientras que foo() es una función con argumentos no especificados.

 4
Author: Some programmer dude,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-01 05:38:14

En C++, no hay diferencia, ambos son iguales.

Ambas definiciones también funcionan en C, pero la segunda definición con void se considera técnicamente mejor, ya que especifica claramente que main solo se puede llamar sin ningún parámetro. En C, si una firma de función no especifica ningún argumento, significa que la función puede ser llamada con cualquier número de parámetros o sin ningún parámetro. Por ejemplo, intente compilar y ejecutar los siguientes dos programas en C (recuerde guardar sus archivos como .c).

 3
Author: Dila Gurung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-23 03:05:05

En primer lugar, hay una diferencia de lo que se permite para los sistemas alojados y los sistemas independientes, como se muestra aquí.

Para los sistemas alojados, se aplica el inicio del programa 5.1.2.2.1:

La función llamada al inicio del programa se llama main. La aplicación declara no prototipo para esta función. Se definirá con un tipo de retorno de int y con no parámetros:

int main(void)

... (sigue más texto con respecto a argv / argc, etc estilo).

La parte interesante es "sin parámetros". int main() y int main (void) son actualmente equivalentes, ya que ambos son declaradores de funciones y no tienen parámetros. Se aplica lo siguiente (6.7.6.3):

10 El caso especial de un parámetro sin nombre de tipo void como único elemento de la lista especifica que la función no tiene parámetros.

/--/

14 Una lista de identificadores declara solo los identificadores de los parámetros de la función. An vaciar list in a function declarator that is part of a definition of that function specifies that the la función no tiene parámetros. La lista vacía en un declarador de función que no es parte de un definition of that function specifies that no information about the number or types of the parámetros se suministra.145)

Énfasis mío, el texto en negrita es lo que se aplica a int main(). También hay nota 145) al final del texto, que dice " Ver "direcciones futuras del lenguaje" (6.11.6)":

6.11.6 Declaradores de funciones

El uso de declaradores de funciones con paréntesis vacíos (no declaradores de tipo de parámetro de formato prototipo) es una característica obsoleta.

Y aquí está la diferencia. Al ser un declarador de funciones, int main()es mal estilo debido a lo anterior, ya que no se garantiza que funcione en la próxima versión del estándar C. Está marcado como una característica obsoleta en C11.

Por lo tanto, siempre debe utilice int main (void) en un sistema alojado y nunca int main(), incluso si las dos formas son, por ahora, equivalentes.


En C++ ambas formas son completamente equivalentes, pero allí int main() es el estilo preferido por razones subjetivas y estéticas (Bjarne Stroustrup lo dice así... lo cual es probablemente una mala justificación para explicar por qué haces algo de una manera particular).

 2
Author: Lundin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:46

En C++, no hay diferencia entre los dos, y int main() es una firma legal y tipo de retorno para main.

 1
Author: juanchopanza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-01 05:31:50

Prototipo de función que tiene Type foo(void) es absolutamente lo mismo que Type foo(), no hay diferencia entre los dos. El anterior puede ser utilizado para la legibilidad.

Al igual que con main - tomando argumentos o no, el programa todavía puede acceder a la información de la línea de comandos a través de otros medios como __argv, __argc, GetCommandLine, u otros símbolos específicos de la plataforma / compilador.

 0
Author: Ajay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-01 05:33:43

Sé que el hilo es viejo, pero esta pregunta me estaba molestando por un tiempo hace unos años, así que quería tirar mi medio centavo(si es que).

Siempre trato las funciones C como si tuvieran una cantidad fija de argumentos independientemente del contexto, a menos que usen va_args. Es decir, confío en main para tener SIEMPRE el prototipo:

int main(int argc, char **argv).

Incluso si no se pasan argumentos, la función tiene estos argumentos en la pila porque la función principal no tiene sobrecarga de funciones.

C tiene la capacidad de tener sobrecarga primitiva a través de solo pretender que el argumento no está allí. En cuyo caso, el argumento todavía se pasa y está en la pila, pero nunca se accede a él, por lo que simplemente reduce el tamaño del código fuente.

Decir int main() simplemente significa que sé que la función puede tener parámetros, pero no los estoy usando, así que escribo int main().

Decir int main (vacío) dice que main CIERTAMENTE no tiene argumentos, e implica que hay dos diferentes prototipos de funciones:

int main(void);
int main(int argc, char **argv);

Dado que C no tiene sobrecarga de funciones, esto es un poco engañoso para mí, y desconfío del código que tiene main(void) en él. No lo haría si main NUNCA tomara ningún parámetro, en cuyo caso main (void) estaría completamente bien.

NOTA: En algunas implementaciones, hay más parámetros en main que argc y argv, como env, pero esto no me molesta porque sé que no digo explícitamente que esos son los únicos dos parámetros, pero esos son los parámetros mínimos y está bien tener más, pero no menos. Esto está en contraste con decir francamente int main (void) que me grita ya que ESTA FUNCIÓN NO TIENE PARÁMETROS, lo cual no es cierto, ya que lo hace, simplemente se omiten.

Aquí está mi código base:

/* sample.c - build into sample. */
#include <stdio.h>

int main(void)
{
    int _argc = *((int *)2686800);
    char ***_pargv = (char ***)2686804;
    int i;

    for (i = 1; i < _argc; ++i) {
        printf("%s ", (*_pargv)[i]);
    }

    return 0;
}

./ muestra I claramente tienen argumentos

La función claramente tiene argumentos pasados a ella, a pesar de salirse del camino para decir explícitamente que no lo hace escribiendo void en el prototipo de la función.

Como eq- dice arriba:

(6.7.6. 3p10) El caso especial de un parámetro sin nombre de tipo void como el solo el elemento de la lista especifica que la función no tiene parámetros.

Así que decir que la función tiene void como argumento, pero en realidad tener argumentos en la pila es una contradicción.

Mi punto es que los argumentos siguen ahí, por lo que afirmar explícitamente que main está vacío de argumentos es deshonesto. La forma honesta sería decir int main (), que afirma nada sobre cuántos parámetros tiene, solo cuántos parámetros le importan.

NOTE2: Los _argc, _pargv son dependientes del sistema, para encontrar sus valores debe encontrarlos ejecutando este programa:

/* findargs.c */
#include <stdio.h>

int main(int argc, char **argv)
{
    printf("address of argc is %u.\n", &argc);
    printf("address of argv is %u.\n", &argv);

    return 0;
}

Estos valores deben permanecer correctos para su sistema específico.

 0
Author: Dmitry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-24 03:26:11