¿Por qué usar un asterisco?[*]” en lugar de un número entero para un parámetro de matriz VLA de una función?

6 minutos de lectura

[*]
trucos

Cuando usas matriz de longitud variable como parámetro en función

int sum(int n, int a[n]);

es fácil de entender el primer parámetro (n) especifica la longitud del segundo parámetro (a). Pero se encontró con otro prototipo utilizado para VLA como parámetro

int sum(int n, int a[*]);

es muy dificil entender por que * se utiliza en lugar de n en el interior []?

  • Lo verificaste int sum(int n, int a[]);

    – Diputado de Midhun

    28 de junio de 2013 a las 18:53

  • [email protected]; si. su función c99.

    – trucos

    28 de junio de 2013 a las 18:54

  • Entonces… en un[*] Qué es una matriz de punteros o una matriz de longitud variable? No es simple de entender con solo ver el código…? Quiero decir… es “int a[*]” lo mismo que “int *a[]”o simplemente” en un[]”?

    – Alejandro Iván

    28 de junio de 2013 a las 18:54


  • Pregunta relacionada/duplicada. Ver respuesta de Jens Gustedt.

    – ajp15243

    28 de junio de 2013 a las 19:03

  • @haccks Si lees el final de su respuesta, esencialmente explica lo que AndreyT explica a continuación, que es que [*] es útil si no nombra sus parámetros de longitud anteriores en sus prototipos de funciones.

    – ajp15243

    28 de junio de 2013 a las 19:11


avatar de usuario
Hormiga

los [*] la sintaxis está destinada a ser utilizada al declarar prototipos de funciones. El detalle clave aquí es que en los prototipos de funciones no es necesario que nombre sus parámetros, solo tiene que especificar el tipo de cada parámetro.

En su ejemplo, si deja el primer parámetro sin nombreentonces obviamente no podrás usar n en su segunda declaración de parámetro (matriz). Sin embargo, en muchos casos debe decirle al compilador que algún parámetro es un VLA. Esto es cuando el [*] la sintaxis viene al rescate.

En su caso, si omite los nombres de los parámetros, el prototipo podría verse como

int sum(int, int [*]);

Sin embargo, es importante señalar que en tu ejemplo específico esta sintaxis es legal, pero no es exactamente necesaria. Al igual que con los arreglos que no son VLA, un int [n] el parámetro sigue siendo equivalente a int * parámetro (incluso para no constante n). Esto significa que simplemente puede crear un prototipo de su función como

int sum(int, int []);

o como

int sum(int, int *);

y el prototipo seguirá cumpliendo su propósito, es decir, coincidirá correctamente con la definición de la función. En otras palabras, las propiedades VLA de un parámetro declarado como una matriz 1D son completamente intrascendentes y el [*] La característica no es realmente necesaria con tales arreglos VLA.

los [*] se vuelve importante en situaciones en las que no se pierde la “matriz variable” del tipo, como sería el caso con 2D VLA (o un puntero a un VLA). Por ejemplo, una función definida como

int sum2d(int n, int m, int a[n][m])
{
  ...
}

podría ser prototipado como cualquiera de los siguientes

int sum2d(int, int, int a[*][*]);
int sum2d(int n, int, int a[n][*]);
int sum2d(int, int m, int a[*][m]);
int sum2d(int n, int m, int a[n][m]);

Todos los prototipos anteriores coinciden correctamente con la definición de la función.

Por supuesto, si tiene la costumbre de nombrar siempre todos los parámetros en los prototipos de funciones, nunca necesitará esto. [*] sintaxis, ya que podrá utilizar el último prototipo de la lista anterior.

PS Nuevamente, como es el caso con todas las matrices en las declaraciones de parámetros, la primera [] siempre es intrascendente y siempre se descompone en un puntero, lo que significa que las siguientes también son declaraciones válidas de prototipos equivalentes para lo anterior sum2d

    int sum2d(int, int, int a[][*]);
    int sum2d(int, int, int (*a)[*]);
    int sum2d(int n, int m, int (*a)[m]);

es el segundo [] eso realmente importa y debe declararse como “longitud variable”.

  • A veces no puede nombrar fácilmente los parámetros en los prototipos. Al escribir un encabezado de biblioteca, desea evitar nombres que puedan entrar en conflicto con los nombres que los usuarios de su biblioteca están usando en macros de preprocesador. Por lo tanto, debe omitir nombres o ingresar al espacio de nombres reservado (en cooperación con la implementación) o hacer que la biblioteca reserve parte del espacio de nombres (como con un prefijo como “MyLibrary_”). Los dos últimos pueden ponerse feos.

    –Eric Postpischil

    28 de junio de 2013 a las 19:21

  • @AndreyT; Por favor elobre su declaración The [*] becomes important in situations when the "variable arrayness" of the type is not lost, as would be the case with 2D VLA. en tu respuesta

    – trucos

    28 de junio de 2013 a las 19:34

  • @EricPostpischil; Salta por encima de la cabeza 🙁

    – trucos

    28 de junio de 2013 a las 19:35

  • @haccks: me refiero al hecho de que el primero [] en la declaración de parámetros de matriz siempre se pierde. El parámetro decae a un puntero. Eso se aplica a todas las declaraciones de parámetros de matriz, independientemente de si son VLA o no. (Lo dije en la respuesta). La única forma de “inyectar” una matriz permanente que no desaparece” en un tipo en C es convertirlo en un puntero a una matriz, como int (*p)[5] o int (*p)[n]. En las declaraciones de parámetros, esto es equivalente a la declaración de matriz 2D.

    – Ant

    28 de junio de 2013 a las 19:44


  • @haccks En el caso de una matriz variable, como int arr[n][m]el compilador necesita saber el tamaño m porque en el caso de un acceso a la matriz como arr[2][3]tiene que convertirlo internamente a algo como *(arr + 2 * m + 3) (Observe la m en la expresión). En ANSI C, su única opción sería pasar int *arr y hacer el *(arr + 1 * m + 1) parte manualmente, pero en C99, puede hacer que el compilador lo maneje por usted, por lo tanto, la nueva sintaxis. El primer tamaño (en este caso n) nunca es necesario, ya que sus elementos siempre están uno al lado del otro (sizeof int bytes en este caso).

    – yyny

    19 de julio de 2020 a las 13:06

avatar de usuario
aaronman

Cuando pones la estrella en una función real da este error test.c:3: error: ‘[*]’ not allowed in other than function prototype scope. Después de algunas investigaciones, esta es en realidad una forma de declarar un VLA en un prototipo de función, con el * en lugar del nombre de la variable. VLA.
El problema en cuestión aquí es que si coloca una variable en lugar de la estrella para un VLA, le dirá que no está declarado, por lo que la estrella es una forma que c99 incorporó para evitar eso.

  • @AlejandroIván Nah, esa es una sintaxis diferente.

    usuario529758

    28 de junio de 2013 a las 18:58

  • Raro… parece que C99 permite matrices de longitud variable declaradas de esta manera.

    – Alejandro Iván

    28 de junio de 2013 a las 18:59

  • @AlejandroIván mira nuevo post

    – aaronman

    28 de junio de 2013 a las 19:03

  • @H2CO3; ¿Qué sintaxis es esta? Es demasiado confuso hombre. Si lo sabe, por favor dé una respuesta.

    – trucos

    28 de junio de 2013 a las 19:04

  • @haccks Matriz de ints: int arr[N]; matriz de punteros a int: int *arr[N]; – puntero-a-matriz-de-ints: int (*ptr)[N]matriz de longitud variable: int arr[<non-const expression>]; – VLA en la lista de argumentos de la función: igual o int arg[*];

    usuario529758

    28 de junio de 2013 a las 19:32

¿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