Vra

Hoe kan ek die grootte van my skikking in C te bepaal?

Dit is, die aantal elemente die skikking kan hou?

Was dit nuttig?

Oplossing

Bestuursopsomming:

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

Full antwoord:

Om die grootte van jou reeks bepaal in grepe, kan jy die sizeof gebruik operateur:

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

Op my rekenaar, SY is 4 grepe lank, so N is 68.

Om die aantal elemente in die skikking te bepaal, kan ons verdeel die totale grootte van die skikking deur die grootte van die skikking element. Jy kan dit doen met die tipe, soos volg:

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

en kry die regte antwoord (68/4 = 17), maar as die tipe a verander sal jy 'n nare fout as jy vergeet het om te verander die sizeof(int) sowel.

So het die voorkeur deler is sizeof(a[0]), die grootte van die zeroeth element van die skikking.

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

Nog 'n voordeel is dat jy nou maklik kan parameteriseren die naam verskeidenheid in 'n makro en kry:

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

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

Ander wenke

Dit is opmerklik dat sizeof nie help wanneer jy met 'n verskeidenheid waarde wat verval na 'n wyser: selfs al is dit wys om die begin van 'n skikking, die samesteller dit is dieselfde as 'n verwysing na 'n enkele element van daardie verskeidenheid. A wyser nie "onthou" enigiets anders oor die skikking wat gebruik is om dit inisialiseer.

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

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

Die sizeof "truuk" is die beste manier wat ek weet, met 'n klein, maar (vir my, dit is 'n groot troeteldier ergeren) belangrike verandering in die gebruik van hakies.

As die Wikipedia-inskrywing duidelik maak, C se sizeof is nie 'n funksie; dit is 'n operateur . So, is dit nie hakies benodig om sy argument, tensy die argument is 'n tipe naam. Dit is maklik om te onthou, want dit maak die argument lyk soos 'n cast uitdrukking, wat ook gebruik hakies.

So: As jy die volgende:

int myArray[10];

Jy kan die aantal elemente met kode soos hierdie te vind:

size_t n = sizeof myArray / sizeof *myArray;

Dit, vir my, lui 'n baie makliker as die alternatief met hakies. Ek bevoordeel ook gebruik van die asterisk in die regterkantste deel van die afdeling, want dit is meer bondige as kruip.

Natuurlik, dit is al te stel-time ook so daar is geen rede tot kommer oor die afdeling wat die prestasie van die program. So gebruik hierdie vorm waar jy kan.

Dit is altyd die beste om sizeof gebruik op 'n werklike voorwerp wanneer jy een, eerder as om op 'n tipe, sedertdien het jy nie hoef te bekommer oor die maak van 'n fout en met vermelding van die verkeerde tipe.

Byvoorbeeld, sê jy het 'n funksie wat 'n paar data uitgange as 'n stroom van grepe, byvoorbeeld oor 'n netwerk. Kom ons noem die funksie send(), en maak dit as argumente 'n verwysing na die voorwerp te stuur, en die aantal grepe in die voorwerp. So, die prototipe word:

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

En dan moet jy 'n heelgetal te stuur, sodat jy dit kodeer up soos volg:

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

Nou, het jy 'n subtiele manier van skiet jouself in die voet, deur die spesifiseer van die tipe foo in twee plekke bekendgestel. As een verander, maar die ander nie, die kode breek. So, doen dit altyd so:

send(&foo, sizeof foo);

Nou kan jy beskerm is. Seker, dupliseer jy die naam van die veranderlike, maar dit het 'n hoë waarskynlikheid van die oortreding van 'n manier die samesteller kan opspoor, as jy dit verander.

Jy kan sizeof operator gebruik, maar dit sal nie werk vir funksies, want dit die verwysing van wyser sal neem Jy kan die volgende doen om die lengte van 'n skikking te vind:

len = sizeof(arr)/sizeof(arr[0])

Kode oorspronklik hier gevind: C program om die aantal elemente in 'n skikking te vind

As jy weet die tipe data van die skikking, kan jy iets soos gebruik:

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

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

Of as jy nie die tipe data van verskeidenheid weet, kan jy iets soos gebruik:

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

Let wel: Hierdie ding werk net as die skikking is nie gedefinieer te hardloop tyd (soos malloc) en die skikking is nie geslaag in 'n funksie. In beide gevalle, arr (array naam) is 'n wyser.

Die makro ARRAYELEMENTCOUNT(x) dat almal gebruik te maak van evalueer verkeerdelik . Dit, realisties, is net 'n sensitiewe saak, omdat jy nie uitdrukkings wat lei tot 'n soort 'n skikking 'kan hê.

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

ARRAYELEMENTCOUNT(p + 1);

Eintlik evalueer as:

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

AANGESIEN

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

ARRAYELEMENTCOUNT(p + 1);

Dit evalueer korrek om:

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

Dit is werklik nie 'n baie te doen met die grootte van skikkings uitdruklik. Ek het net 'n klomp foute agtergekom uit nie werklik waarneem hoe die C preprocessor werk. Jy draai altyd die makro parameter, nie 'n uitdrukking in kan betrokke wees in.


Dit is korrek; my voorbeeld was 'n slegte een. Maar dit is eintlik presies wat moet gebeur. Soos ek voorheen genoem p + 1 sal eindig as 'n wyser tipe en ongeldig die hele makro (net soos as jy probeer om die makro gebruik in 'n funksie met 'n wyser parameter).

Aan die einde van die dag, in hierdie veral byvoorbeeld die skuld maak nie regtig saak (so ek is net mors almal se tyd;! Huzzah), omdat jy nie uitdrukkings met 'n soort van 'n skikking. Maar regtig die punt oor voorverwerker evaluering subtles ek dink is 'n belangrike een.

Vir multidimensionele skikkings Dit is 'n bietjie meer ingewikkeld. Oftenly mense definieer eksplisiete makro konstantes, maw

#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",        " " },
};

Maar hierdie konstantes kan tydens kompilering-time geëvalueer te met 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);

Let daarop dat hierdie kode werk in C en C ++. Vir skikkings met meer as twee dimensies gebruik

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

ens., Ad infinitum.

Grootte van 'n skikking in 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
sizeof(array) / sizeof(array[0])
#define SIZE_OF_ARRAY(_array) (sizeof(_array) / sizeof(_array[0]))

"jy het 'n subtiele manier van skiet jouself in die voet ingestel"

C 'inheems' skikkings nie hul grootte te stoor. Dit word dus aanbeveel om die lengte van die skikking in 'n aparte veranderlike / konst red, en slaag dit wanneer jy die skikking te slaag, dit wil sê:

#define MY_ARRAY_LENGTH   15
int myArray[MY_ARRAY_LENGTH];

Jy moet altyd vermy moedertaal skikkings (tensy jy kan nie, in welke geval, omgee jou voet). As jy skryf C ++, gebruik die STL se "vektor 'n houer. "In vergelyking met skikkings, verskaf hulle byna dieselfde prestasie", en hulle is baie meer nuttig!

// vector is a template, the <int> means it is a vector of ints
vector<int> numbers;  

// push_back() puts a new value at the end (or back) of the vector
for (int i = 0; i < 10; i++)
    numbers.push_back(i);

// Determine the size of the array
cout << numbers.size();

Sien: http://www.cplusplus.com/reference/stl/vector/

@ Magnus: Die standaard definieer sizeof as opbrengs van die aantal grepe in die voorwerp en dat sizeof (char) is altyd een. Die aantal bisse in 'n byte is implementering spesifieke.

Edit: ANSI C ++ standaard afdeling 5.3.3 sizeof:

  

Die sizeof operator lewer die aantal grepe in die voorwerp voorstelling van sy operand. [...] sizeof (char), sizeof (onderteken char) en sizeof (unsigned char) is 1; die gevolg van sizeof toegepas op enige ander fundamentele tipe is-implementering omskryf.

Artikel 1.6 Die C ++ geheue model:

  

Die fundamentele stoor eenheid in die C ++ geheue model is die byte. A byte is ten minste groot genoeg is om 'n lid van die basiese uitvoering karakter stel bevat en is saamgestel uit 'n aangrensende volgorde van stukkies, die aantal wat-implementering omskryf.

  

@Skizz: Ek is redelik seker dat ek reg, alhoewel die beste "bron" Ek kan jou op die oomblik gee is Wikipedia, uit die artikel oor sizeof:

Wikipedia is verkeerd, Skizz reg is. sizeof (char) is 1, per definisie.

Ek bedoel, net lees die Wikipedia-inskrywing regtig nou om te sien dat dit verkeerd is. "Veelvoude van char". sizeof(char) kan nooit iets wees ander as "1". As dit was, sê, 2, sou dit beteken dat sizeof(char) was twee keer die grootte van char!

As jy regtig wil om dit te doen om te slaag om jou array Ek stel voor die implementering van 'n struktuur om 'n wyser te slaan na die tipe wat jy 'n verskeidenheid van en 'n heelgetal wat die grootte van die skikking wil. Dan kan jy slaag wat rondom jou funksies. Net toewys die skikking veranderlike waarde (wyser na die eerste element) na wat wyser. Dan kan jy gaan Array.arr[i] om die i-de element te kry en te gebruik Array.size om die aantal elemente in die skikking te kry.

Ek sluit 'n paar kode vir julle. Dit is nie baie nuttig, maar jy kan dit uit te brei met meer funksies. Om al eerlik te wees, indien dit is die dinge wat jy wil jy moet ophou met behulp van C en gebruik 'n ander taal met hierdie eienskappe gebou in.

/* 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;
}

Die beste manier is jy hierdie inligting te red, byvoorbeeld, in 'n struktuur:

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

Implementering van al die nodige funksies soos skep, te vernietig, maak seker gelykheid, en alles wat jy nodig het. Dit is makliker om te slaag as 'n parameter.

Die funksie sizeof terug Die nommer van grepe wat gebruik word deur jou opgestel in die geheue. As jy wil hê dat die aantal elemente in jou reeks te bereken, moet jy dat die getal met die sizeof veranderlike tipe van die skikking te verdeel. Kom ons sê int array[10];, as veranderlike tipe integer in jou rekenaar is 32 bit (of 4 grepe), ten einde die grootte van jou reeks te kry, moet jy die volgende doen:

int array[10];
int sizeOfArray = sizeof(array)/sizeof(int);

Jy kan die & operateur gebruik. Hier is die bron-kode:

#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;
};

Hier is die voorbeeld uitvoer

1549216672
1549216712
---- diff----
4
The size of array a is 10
int a[10];
int size = (*(&a+1)-a) ;

Vir meer besonderhede sien hier en ook hier .

Voorbeeld

#include <stdio.h>

int main() {
    int size;
    scanf("%d", &size);
    int array[size];
    printf("%d\n", (int) (sizeof(array) / sizeof(int)));
    printf("%d\n", (int) (sizeof(array) / sizeof(array[0])));
    return 0;
}
Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top