inicializando una matriz de ints

7 minutos de lectura

avatar de usuario
Miguel

¿Alguien tiene una manera de inicializar una matriz de ints (cualquier tipo de varios bytes está bien realmente), a un valor distinto de cero y distinto de -1 simplemente? Con lo que quiero decir, ¿hay alguna manera de hacer esto en una sola línea, sin tener que hacer cada elemento individualmente?

int arr[30] = {1, 1, 1, 1, ...}; // that works, but takes too long to type

int arr[30] = {1}; // nope, that gives 1, 0, 0, 0, ...

int arr[30];
memset(arr, 1, sizeof(arr)); // That doesn't work correctly for arrays with multi-byte
                             //   types such as int

Solo para tu información, usando memset() de esta manera en arreglos estáticos da:

arr[0] = 0x01010101
arr[1] = 0x01010101
arr[2] = 0x01010101

La otra opción:

for(count = 0; count < 30; count++)
   arr[count] = 1;    // Yup, that does it, but it's two lines.

¿Alguien tiene otras ideas? Mientras sea código C, no hay límites en la solución. (otras librerías están bien)

  • hay wmemset() para arreglos de caracteres “anchos”

    – Marc B.

    20 de noviembre de 2012 a las 16:10

  • ¿Otras bibliotecas no requerirían> 1 línea? #include libother

    – mcalex

    20 de noviembre de 2012 a las 16:12

  • @MarcB – No está mal … dos problemas menores, primero entiendo wchar_t is compiler-specific and can be as small as 8 bits por lo que podría ser un solo byte. En segundo lugar, esperaba algo que pudiera funcionar en diferentes tipos. Pero no es una mala sugerencia. Gracias.

    – Miguel

    20 de noviembre de 2012 a las 16:18

  • Mac OS X tiene memset_pattern4(), memset_pattern8() y memset_pattern16() desde la versión 10.5.

    – Pascal Cuoq

    20 de noviembre de 2012 a las 16:19

  • @mcalex – Touché. Ok, ¿qué tal “1 delineador por configuración”, no contaremos #includes o más opciones para gcc

    – Miguel

    20 de noviembre de 2012 a las 16:19

avatar de usuario
iabdalkader

Esta es una extensión GCC:

int a[100] = {[0 ... 99] = 1};

  • Eso es impresionante, no estaba al tanto de la sintaxis. +1

    – Miguel

    20 noviembre 2012 a las 19:00

  • Nota para cualquier otra persona que use esto, hay un espacio en blanco entre los dígitos y el ... lo cual es importante

    – Miguel

    20 de noviembre de 2012 a las 19:04

  • @Mike verifique el enlace, también puede inicializar múltiples rangos y elementos individuales.

    – iabdalkader

    20 de noviembre de 2012 a las 19:23

  • Corríjame si me equivoco, pero los inicializadores designados en el lenguaje C son: typedef struct { int x; int y} type; luego type t = { .x=1, .y=2 }; Nunca he visto la notación .. ni he oído hablar de ella como inicializador designado. Creo que esta es una extensión GCC más allá de los inicializadores designados C estándar.

    – Lundin

    21 de noviembre de 2012 a las 7:49

  • @Lundin es una extensión GCC, como mencioné, y se describe en el enlace a continuación Inicializadores designados sección. mi respuesta fue editada, no estoy seguro de cómo se llama, pero creo que tal vez “inicializador de rango” sea más apropiado.

    – iabdalkader

    21 de noviembre de 2012 a las 7:57

for (count = 0; count < 30; count++) arr[count] = 1;

Una línea. 🙂

  • One line. :) muy cierto… se siguio al pie de la letra con esta solucion

    – Miguel

    20 de noviembre de 2012 a las 17:29

avatar de usuario
Omkant

Dijiste algo sobre 2 líneas, pero puedes hacerlo en una línea usando coma ,operador.

for(count = 0; count < 30 ; arr[count] = 1,count++);

  • De hecho, me gusta esta solución, la , El operador está tan poco utilizado.

    – Miguel

    20 de noviembre de 2012 a las 17:30

  • ¿Qué coma, el operador no se usa? no te entendí

    – Omkant

    20 de noviembre de 2012 a las 17:35

  • Voy a reformular, “Me gusta esta solución porque usa el operador de coma, y ​​la gente no lo usa lo suficiente”.

    – Miguel

    20 de noviembre de 2012 a las 17:48

  • Alternativamente: for(count = 0; count < 30; arr[count++] = 1);

    – hammar

    21 de noviembre de 2012 a las 5:27


  • También puede escribir todo su programa en C en una sola línea. Si alguien pudiera proporcionar una razón fundamental sobre cómo eso tiene sentido, me encantaría escucharlo.

    – Lundin

    21 de noviembre de 2012 a las 12:30

avatar de usuario
Lundin

La única forma sensata de hacer esto durante la inicialización (en lugar del tiempo de ejecución) parece ser:

#define ONE1     1
#define FIVE1    ONE1, ONE1, ONE1, ONE1, ONE1
#define TEN1     FIVE1, FIVE1
#define TWENTY1  TEN1, TEN1
#define FIFTY1   TWENTY1, TWENTY1, TEN1
#define HUNDRED1 FIFTY1, FIFTY1

int array [100][4] =
{
  HUNDRED1,
  HUNDRED1,
  HUNDRED1,
  HUNDRED1
};

Y después, #define ONE2 2 y así. Entiendes la idea.

EDITAR: La razón por la que escribí tantas macros fue para demostrar cuán flexible es esta solución. Para este caso en particular no los necesita todos. Pero con macros como estas puedes escribir cualquier tipo de lista de inicializadores de forma rápida y flexible:

{
  FIFTY1, FIFTY2,  // 1,1,1,1... 50 times, then 2,2,2,2... 50 times
  TWENTY3, EIGHTY4 // 3,3,3,3... 20 times, then 4,4,4,4... 80 times
  ... // and so on
};

avatar de usuario
Hormiga

En C, normalmente desarrolla su propia “biblioteca de soporte” con macros como

#define SET_ALL(a_, n_, v_)\
  do { size_t i, n = (n_); for (i = 0; i < n; ++i) (a_)[i] = (v_); } while(0)

#define SET_ALL_A(a_, v_) SET_ALL(a_, sizeof(a_) / sizeof *(a_), v_)
#define ZERO_ALL(a_, n_) SET_ALL(a_, n_, 0)
#define ZERO_ALL_A(a_) SET_ALL_A(a_, 0)

y luego utilícelos en su código como

int arr[30];

SET_ALL_A(arr, 1);

  • Ese es realmente un punto importante, por qué no pensé en incluir solo una macro para encargarme de eso, está más allá de mí…

    – Miguel

    20 de noviembre de 2012 a las 17:24

  • Si crea una macro repugnante como esta, ¿por qué no escribir una para realmente inicializar la matriz, en lugar de establecerla en tiempo de ejecución de esta manera? Suponga que “arr” tiene una duración de almacenamiento estática y desea aprovechar las reglas de inicialización especiales para tales variables (se inicializan antes de que se llame a main).

    – Lundin

    21 de noviembre de 2012 a las 12:27

  • @Lundin: si tuviera conocimiento de alguna característica de C que me permitiera inicializar la matriz según lo solicitado, la usaría. Pero, por desgracia, no tengo ni idea de cómo hacerlo. Veo la “macro repulsiva” anterior como lo mejor disponible en C. Si puede sugerir algo mejor, soy todo oídos.

    – Ant

    21 de noviembre de 2012 a las 16:01


avatar de usuario
Archie

¡Una línea con punteros!

for (int *p = a; p < (a + 30); p++) *p = 1;

o si eres prematuramente miedo al impacto en el rendimiento causado por el cálculo repetido (a + 30):

for (int *p = a + 30 - 1; p >= a; p--) *p = 1;

  • Ese es realmente un punto importante, por qué no pensé en incluir solo una macro para encargarme de eso, está más allá de mí…

    – Miguel

    20 de noviembre de 2012 a las 17:24

  • Si crea una macro repugnante como esta, ¿por qué no escribir una para realmente inicializar la matriz, en lugar de establecerla en tiempo de ejecución de esta manera? Suponga que “arr” tiene una duración de almacenamiento estática y desea aprovechar las reglas de inicialización especiales para tales variables (se inicializan antes de que se llame a main).

    – Lundin

    21 de noviembre de 2012 a las 12:27

  • @Lundin: si tuviera conocimiento de alguna característica de C que me permitiera inicializar la matriz según lo solicitado, la usaría. Pero, por desgracia, no tengo ni idea de cómo hacerlo. Veo la “macro repulsiva” anterior como lo mejor disponible en C. Si puede sugerir algo mejor, soy todo oídos.

    – Ant

    21 de noviembre de 2012 a las 16:01


avatar de usuario
ConejoCurioso

Para la inicialización a un valor estático, generalmente he considerado escribirlo como preferido, como en:

int arr[30] = {1, 1, 1, 1, ...}; 

En este caso, el compilador puede (y generalmente lo hace) generar una inicialización optimizada en el código de preámbulo.

A veces la inicialización es más dinámica, como en este ejemplo:

int arr[30];
int x = fetchSomeValue();
for(int i=0; i<30; i++) arr[i] = x;

En estos casos, debe codificarlo y la regla general es maximizar la legibilidad, no minimizar la escritura. Este código se escribirá una vez y se leerá multitud de veces.

¿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