arrays matrices - ¿Cómo puedo determinar el tamaño de mi matriz en C?




vectores ejemplos (18)

¿Cómo puedo determinar el tamaño de mi matriz en C?

Es decir, ¿el número de elementos que la matriz puede contener?


Answers

Si conoce el tipo de datos de la matriz, puede usar algo como:

int arr[] = {23, 12, 423, 43, 21, 43, 65, 76, 22};

int noofele = sizeof(arr)/sizeof(int);

O si no conoce el tipo de datos de la matriz, puede usar algo como:

noofele = sizeof(arr)/sizeof(arr[0]);

Nota: Esto solo funciona si la matriz no está definida en tiempo de ejecución (como malloc) y la matriz no se pasa en una función. En ambos casos, arr (nombre de la matriz) es un puntero.


#define SIZE_OF_ARRAY(_array) (sizeof(_array) / sizeof(_array[0]))

@Skizz: Estoy bastante seguro de que tengo razón, aunque la mejor "fuente" que puedo ofrecerle en este momento es Wikipedia, del artículo sobre sizeof:

Wikipedia está mal, Skizz tiene razón. sizeof (char) es 1, por definición.

Quiero decir, simplemente lea la entrada de Wikipedia muy de cerca para ver que está mal. "múltiplos de char". sizeof(char) nunca puede ser otra cosa que "1". Si fuera, digamos, 2, significaría que sizeof(char) era dos veces el tamaño de char!


Para matrices multidimensionales es un poco más complicado. A menudo las personas definen constantes macro explícitas, es decir

#define g_rgDialogRows   2
#define g_rgDialogCols   7

static char const* g_rgDialog[g_rgDialogRows][g_rgDialogCols] =
{
    { " ",  " ",    " ",    " 494", " 210", " Generic Sample Dialog", " " },
    { " 1", " 330", " 174", " 88",  " ",    " OK",        " " },
};

Pero estas constantes también pueden evaluarse en tiempo de compilación con sizeof :

#define rows_of_array(name)       \
    (sizeof(name   ) / sizeof(name[0][0]) / columns_of_array(name))
#define columns_of_array(name)    \
    (sizeof(name[0]) / sizeof(name[0][0]))

static char* g_rgDialog[][7] = { /* ... */ };

assert(   rows_of_array(g_rgDialog) == 2);
assert(columns_of_array(g_rgDialog) == 7);

Tenga en cuenta que este código funciona en C y C ++. Para matrices con más de dos dimensiones de uso.

sizeof(name[0][0][0])
sizeof(name[0][0][0][0])

etc., hasta el infinito.


int size = (&arr)[1] - arr;

Echa un vistazo a este enlace para la explicación


La mejor manera es guardar esta información, por ejemplo, en una estructura:

typedef struct {
     int *array;
     int elements;
} list_s;

Implemente todas las funciones necesarias, como crear, destruir, verificar la igualdad y todo lo que necesite. Es más fácil pasar como parámetro.


Si realmente desea hacer esto para pasar su matriz, sugiero implementar una estructura para almacenar un puntero al tipo del que desea una matriz y un entero que represente el tamaño de la matriz. Entonces puedes pasar eso a tus funciones. Simplemente asigne el valor de la variable de la matriz (puntero al primer elemento) a ese puntero. Luego puede ir a Array.arr[i] para obtener el elemento i-th y usar Array.size para obtener el número de elementos de la matriz.

Incluí un código para ti. No es muy útil, pero podría ampliarlo con más funciones. Sin embargo, para ser honesto, si estas son las cosas que deseas, debes dejar de usar C y usar otro idioma con estas características incorporadas.

/* Absolutely no one should use this...
   By the time you're done implementing it you'll wish you just passed around
   an array and size to your functions */
/* This is a static implementation. You can get a dynamic implementation and 
   cut out the array in main by using the stdlib memory allocation methods,
   but it will work much slower since it will store your array on the heap */

#include <stdio.h>
#include <string.h>
/*
#include "MyTypeArray.h"
*/
/* MyTypeArray.h 
#ifndef MYTYPE_ARRAY
#define MYTYPE_ARRAY
*/
typedef struct MyType
{
   int age;
   char name[20];
} MyType;
typedef struct MyTypeArray
{
   int size;
   MyType *arr;
} MyTypeArray;

MyType new_MyType(int age, char *name);
MyTypeArray newMyTypeArray(int size, MyType *first);
/*
#endif
End MyTypeArray.h */

/* MyTypeArray.c */
MyType new_MyType(int age, char *name)
{
   MyType d;
   d.age = age;
   strcpy(d.name, name);
   return d;
}

MyTypeArray new_MyTypeArray(int size, MyType *first)
{
   MyTypeArray d;
   d.size = size;
   d.arr = first;
   return d;
}
/* End MyTypeArray.c */


void print_MyType_names(MyTypeArray d)
{
   int i;
   for (i = 0; i < d.size; i++)
   {
      printf("Name: %s, Age: %d\n", d.arr[i].name, d.arr[i].age);
   }
}

int main()
{
   /* First create an array on the stack to store our elements in.
      Note we could create an empty array with a size instead and
      set the elements later. */
   MyType arr[] = {new_MyType(10, "Sam"), new_MyType(3, "Baxter")};
   /* Now create a "MyTypeArray" which will use the array we just
      created internally. Really it will just store the value of the pointer
      "arr". Here we are manually setting the size. You can use the sizeof
      trick here instead if you're sure it will work with your compiler. */
   MyTypeArray array = new_MyTypeArray(2, arr);
   /* MyTypeArray array = new_MyTypeArray(sizeof(arr)/sizeof(arr[0]), arr); */
   print_MyType_names(array);
   return 0;
}

Vale la pena señalar que sizeof no ayuda cuando se trata de un valor de matriz que se ha reducido a un puntero: aunque apunta al inicio de una matriz, al compilador es lo mismo que un puntero a un solo elemento de esa matriz formación. Un puntero no "recuerda" nada más sobre la matriz que se utilizó para inicializarla.

int a[10];
int* p = a;

assert(sizeof(a) / sizeof(a[0]) == 10);
assert(sizeof(p) == sizeof(int*));
assert(sizeof(*p) == sizeof(int));

Puede utilizar el operador & . Aquí está el código fuente:

#include<stdio.h>
#include<stdlib.h>
int main(){

    int a[10];

    int *p; 

    printf("%p\n", (void *)a); 
    printf("%p\n", (void *)(&a+1));
    printf("---- diff----\n");
    printf("%zu\n", sizeof(a[0]));
    printf("The size of array a is %zu\n", ((char *)(&a+1)-(char *)a)/(sizeof(a[0])));


    return 0;
};

Aquí está la salida de muestra

1549216672
1549216712
---- diff----
4
The size of array a is 10

El sizeof es la forma correcta iff está tratando con matrices no recibidas como parámetros. Una matriz enviada como un parámetro a una función se trata como un puntero, por lo que sizeof devolverá el tamaño del puntero, en lugar de la matriz.

Por lo tanto, dentro de las funciones de este método no funciona. En su lugar, siempre pase un size_t size parámetro adicional size_t size indique el número de elementos en la matriz.

Prueba:

#include <stdio.h>
#include <stdlib.h>

void printSizeOf(int intArray[]);
void printLength(int intArray[]);

int main(int argc, char* argv[])
{
    int array[] = { 0, 1, 2, 3, 4, 5, 6 };

    printf("sizeof of array: %d\n", (int) sizeof(array));
    printSizeOf(array);

    printf("Length of array: %d\n", (int)( sizeof(array) / sizeof(array[0]) ));
    printLength(array);
}

void printSizeOf(int intArray[])
{
    printf("sizeof of parameter: %d\n", (int) sizeof(intArray));
}

void printLength(int intArray[])
{
    printf("Length of parameter: %d\n", (int)( sizeof(intArray) / sizeof(intArray[0]) ));
}

Salida (en un sistema operativo Linux de 64 bits):

sizeof of array: 28
sizeof of parameter: 8
Length of array: 7
Length of parameter: 2

Salida (en un sistema operativo Windows de 32 bits):

sizeof of array: 28
sizeof of parameter: 4
Length of array: 7
Length of parameter: 1

sizeof(array) / sizeof(array[0])

Resumen ejecutivo:

int a[17];
size_t n = sizeof(a)/sizeof(a[0]);

Para determinar el tamaño de su matriz en bytes, puede usar el operador sizeof :

int a[17];
size_t n = sizeof(a);

En mi computadora, los ints tienen una longitud de 4 bytes, por lo que n es 68.

Para determinar el número de elementos en la matriz, podemos dividir el tamaño total de la matriz por el tamaño del elemento de la matriz. Podrías hacer esto con el tipo, como este:

int a[17];
size_t n = sizeof(a) / sizeof(int);

y obtenga la respuesta correcta (68/4 = 17), pero si cambia el tipo de error, tendrá un error desagradable si se olvida de cambiar también el sizeof(int) .

Así que el divisor preferido es sizeof(a[0]) , el tamaño del elemento ceroet de la matriz.

int a[17];
size_t n = sizeof(a) / sizeof(a[0]);

Otra ventaja es que ahora puede parametrizar fácilmente el nombre de la matriz en una macro y obtener:

#define NELEMS(x)  (sizeof(x) / sizeof((x)[0]))

int a[17];
size_t n = NELEMS(a);

La macro ARRAYELEMENTCOUNT(x) que todos están haciendo uso de evalúa incorrectamente . Esto, de manera realista, es solo un asunto delicado, porque no puede haber expresiones que resulten en un tipo de "matriz".

/* Compile as: CL /P "macro.c" */
# define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x[0]))

ARRAYELEMENTCOUNT(p + 1);

En realidad evalúa como:

(sizeof (p + 1) / sizeof (p + 1[0]));

Mientras

/* Compile as: CL /P "macro.c" */
# define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x)[0])

ARRAYELEMENTCOUNT(p + 1);

Se evalúa correctamente a:

(sizeof (p + 1) / sizeof (p + 1)[0]);

Esto realmente no tiene mucho que ver con el tamaño de los arreglos explícitamente. Acabo de notar muchos errores al no observar realmente cómo funciona el preprocesador de C. Siempre envuelve el parámetro de macro, no se puede involucrar una expresión en.

Esto es correcto; Mi ejemplo fue malo. Pero eso es exactamente lo que debería suceder. Como mencioné anteriormente, p + 1 terminará como un tipo de puntero e invalidará toda la macro (como si intentara usar la macro en una función con un parámetro de puntero).

Al final del día, en este caso en particular , la falla no importa realmente (así que solo estoy perdiendo el tiempo de todos, ¡huzzah!), Porque no tiene expresiones con un tipo de 'matriz'. Pero en realidad, el punto sobre los subartículos de evaluación del preprocesador creo que es importante.


@ Magnus: El estándar define sizeof como que produce el número de bytes en el objeto y que sizeof (char) siempre es uno. La cantidad de bits en un byte es específica de la implementación.

Edición: ANSI C ++ estándar sección 5.3.3 Sizeof:

El operador sizeof produce el número de bytes en la representación del objeto de su operando. [...] sizeof (char), sizeof (signed char) y sizeof (unsigned char) son 1; el resultado de sizeof aplicado a cualquier otro tipo fundamental está definido por la implementación.

Sección 1.6 El modelo de memoria C ++:

La unidad de almacenamiento fundamental en el modelo de memoria C ++ es el byte. Un byte es al menos lo suficientemente grande como para contener cualquier miembro del conjunto básico de caracteres de ejecución y está compuesto por una secuencia contigua de bits, cuyo número está definido por la implementación.


El tamaño del "truco" es la mejor manera que conozco, con un pequeño pero importante (para mí, que es un motivo importante para las mascotas) un cambio importante en el uso del paréntesis.

Como deja claro la entrada de Wikipedia, el sizeof de C no es una función; es un operador Por lo tanto, no requiere paréntesis alrededor de su argumento, a menos que el argumento sea un nombre de tipo. Esto es fácil de recordar, ya que hace que el argumento se vea como una expresión de conversión, que también usa paréntesis.

Entonces: Si tienes lo siguiente:

int myArray[10];

Puedes encontrar el número de elementos con código como este:

size_t n = sizeof myArray / sizeof *myArray;

Eso, para mí, es mucho más fácil que la alternativa con paréntesis. También estoy a favor del uso del asterisco en la parte derecha de la división, ya que es más conciso que la indexación.

Por supuesto, todo esto también es tiempo de compilación, por lo que no hay que preocuparse por la división que afecta el rendimiento del programa. Así que usa este formulario siempre que puedas.

Siempre es mejor usar sizeof en un objeto real cuando tiene uno, en lugar de en un tipo, ya que entonces no necesita preocuparse por cometer un error e indicar el tipo incorrecto.

Por ejemplo, supongamos que tiene una función que genera algunos datos como un flujo de bytes, por ejemplo, a través de una red. Llamemos a la función send() y hagamos que tomen como argumentos un puntero al objeto a enviar y el número de bytes en el objeto. Así, el prototipo se convierte en:

void send(const void *object, size_t size);

Y luego necesitas enviar un número entero, así que lo codificas así:

int foo = 4711;
send(&foo, sizeof (int));

Ahora, has introducido una forma sutil de dispararte en el pie, especificando el tipo de foo en dos lugares. Si uno cambia pero el otro no, el código se rompe. Así, siempre hazlo así:

send(&foo, sizeof foo);

Ahora estás protegido. Claro, duplica el nombre de la variable, pero eso tiene una alta probabilidad de interrumpir de una manera que el compilador pueda detectar, si la cambia.


 int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };
 int len = (int) sizeof(arr) / sizeof(*arr);
 printf("%d\n", len);

Tamaño de una matriz en C:

int a[10];
size_t size_of_array = sizeof(a);      // Size of array a
int n = sizeof (a) / sizeof (a[0]);    // Number of elements in array a
size_t size_of_element = sizeof(a[0]); // Size of each element in array a                                          
                                       // Size of each element = size of type

<?php
    $stack = array("fruit1", "fruit2", "fruit3", "fruit4");
    $fruit = array_shift($stack);
    print_r($stack);

    echo $fruit;
?>

Salida:

Array
(
    [0] => fruit2
    [1] => fruit3
    [2] => fruit4
)

fruit1




c arrays memory