Wat is Size_t in C?

Ik word verward met size_tin C. Ik weet dat het wordt geretourneerd door de sizeofoperator. Maar wat is het precies? Is het een gegevenstype?

Laten we zeggen dat ik een forlus hebben:

for(i = 0; i < some_size; i++)

Moet ik int i;of size_t i;?


Antwoord 1, Autoriteit 100%

van Wikipedia :

Volgens de ISO C-standaard 1999
(C99), size_tis een niet-ondertekend geheel getal
Type van minimaal 16 bit (zie secties
7.17 en 7.18.3).

size_tis een niet-ondertekend gegevenstype
gedefinieerd door verschillende C / C++ normen,
b.v. de C9NE ISO / IEC 9899-standaard,
Dat is gedefinieerd in stddef.h. 1 het kan
verder worden geïmporteerd door opname van
stdlib.hals dit bestand intern sub
Omvat stddef.h.

Dit type wordt gebruikt om de
grootte van een object. Bibliotheekfuncties
die maten innemen of retourneren dat ze ze verwachten
om van het type te zijn of het retourtype te hebben
van size_t. Verder het meest
Veelgebruikte compiler-gebaseerd
Operator Maat moet evalueren op een
constante waarde die compatibel is met
size_t.

Als een implicatie, size_tis een type gegarandeerd om een ​​array-index vast te houden.


Antwoord 2, Autoriteit 50%

size_tis een niet-ondertekend type. Dus, het kan geen negatieve waarden (& lt; 0) vertegenwoordigen. Je gebruikt het als je iets telt, en zeker weet dat het niet negatief kan zijn. Bijvoorbeeld, strlen()retourneert een size_tOmdat de lengte van een string minimaal 0 moet zijn.

In uw voorbeeld, als uw lus-index altijd groter is dan 0, kan het logisch zijn om size_tof een ander niet-ondertekend gegevenstype te gebruiken.

Wanneer u een size_tObject gebruikt, moet u ervoor zorgen dat in alle contexten die het wordt gebruikt, inclusief rekenkunde, u niet-negatieve waarden wilt. Laten we bijvoorbeeld zeggen dat je hebt:

size_t s1 = strlen(str1);
size_t s2 = strlen(str2);

en u wilt het verschil van de lengtes van str2en str1vinden. U kunt niet doen:

int diff = s2 - s1; /* bad */

Dit komt omdat de waarde die is toegewezen aan diffaltijd een positief getal zal zijn, zelfs wanneer s2 < s1, omdat de berekening wordt gedaan met niet-ondertekende typen. In dit geval, afhankelijk van wat uw gebruikscase is, is u misschien beter af met behulp van int(of long long) voor s1en s2.

Er zijn enkele functies in C / POSIX die / zou kunnen gebruiken size_t, maar niet vanwege historische redenen. De tweede parameter op fgetsmoet bijvoorbeeld idealiter size_tzijn, maar is int.


Antwoord 3, Autoriteit 18%

size_tis een type dat een array-index kan bevatten.

Afhankelijk van de implementatie kan het een van:

zijn

unsigned char

unsigned short

unsigned int

unsigned long

unsigned long long

Hier is hoe size_tis gedefinieerd in stddef.hvan mijn machine:

typedef unsigned long size_t;

Antwoord 4, Autoriteit 16%

Als u het empirische type bent,

echo | gcc -E -xc -include 'stddef.h' - | grep size_t

Uitvoer voor Ubuntu 14.04 64-bit GCC 4.8:

typedef long unsigned int size_t;

Merk op dat stddef.hwordt verschaft door GCC en niet GLIBC onder src/gcc/ginclude/stddef.hIN GCC 4.2.

Interessant C95-optredens

  • mallocNeemt size_tals een argument, dus het bepaalt de maximale grootte die kan worden toegewezen.

    en aangezien het ook wordt geretourneerd door sizeof, denk ik dat het de maximale grootte van elke array beperkt.

    Zie ook: Wat is de maximale grootte van een array in C ?


Antwoord 5, Autoriteit 5%

De mandpagina voor types.h zegt:

SIFT_T is een niet-ondertekend geheel getal


Antwoord 6, Autoriteit 4%

Omdat nog niemand het heeft genoemd, is de belangrijkste taalkundige betekenis van size_tdat de operator sizeofeen waarde van dat type retourneert. Evenzo is de primaire betekenis van ptrdiff_tdat het aftrekken van de ene aanwijzer van de andere een waarde van dat type oplevert. Bibliotheekfuncties die dit accepteren, doen dit omdat dergelijke functies kunnen werken met objecten waarvan de grootte groter is dan UINT_MAX op systemen waar dergelijke objecten zouden kunnen bestaan, zonder dat bellers worden gedwongen code te verspillen die een waarde groter dan “unsigned int” doorgeeft op systemen waar het grotere type zou volstaan voor alle mogelijke objecten.


Antwoord 7, autoriteit 3%

Om in te gaan waarom size_tmoest bestaan en hoe we hier kwamen:

Pragmatisch gezien zijn size_ten ptrdiff_tgegarandeerd 64 bits breed bij een 64-bits implementatie, 32 bits breed bij een 32-bits implementatie, enzovoort. Aan. Ze konden geen enkel bestaand type dwingen om dat te betekenen, op elke compiler, zonder de oude code te breken.

Een size_tof ptrdiff_tis niet noodzakelijk hetzelfde als een intptr_tof uintptr_t. Ze waren anders op bepaalde architecturen die nog in gebruik waren toen size_ten ptrdiff_teind jaren tachtig aan de standaard werden toegevoegd, en verouderd raakten toen C99heeft veel nieuwe typen toegevoegd, maar nog niet verdwenen (zoals 16-bit Windows). De x86 in 16-bits beveiligde modus had een gesegmenteerd geheugen waar de grootst mogelijke array of structuur slechts 65.536 bytes groot kon zijn, maar een farpointer moest 32 bits breed zijn, breder dan de registers. Daarop zou intptr_t32 bits breed zijn, maar size_ten ptrdiff_tzouden 16 bits breed kunnen zijn en in een register passen. En wie wist wat voor soort besturingssysteem er in de toekomst zou kunnen worden geschreven? In theorie biedt de i386-architectuur een 32-bits segmentatiemodel met 48-bits pointers die geen enkel besturingssysteem ooit heeft gebruikt.

Het type geheugenoffset kan niet longzijn, omdat veel te veel oude code ervan uitgaat dat longprecies 32 bits breed is. Deze veronderstelling was zelfs ingebouwd in de UNIX- en Windows-API’s. Helaas gingen veel andere oude code er ook van uit dat een longbreed genoeg is om een aanwijzer, een bestandsoffset, het aantal seconden dat is verstreken sinds 1970, enzovoort te bevatten. POSIX biedt nu een gestandaardiseerde manier om de laatste veronderstelling waar te maken in plaats van de eerste, maar geen van beide is een draagbare veronderstelling om te maken.

Het kan niet intzijn omdat slechts een handvol compilers in de jaren ’90 int64 bits breed maakten. Toen werden ze echt raar door long32 bits breed te houden. De volgende herziening van de standaard verklaarde het onwettig voor intom breder te zijn dan long, maar intis nog steeds 32 bits breed op de meeste 64-bits systemen.

Het kan geen long long intzijn, die sowieso later is toegevoegd, aangezien die is gemaakt om ten minste 64 bits breed te zijn, zelfs op 32-bits systemen.

Er was dus een nieuw type nodig. Zelfs als dat niet zo was, betekenden al die andere typen iets anders dan een offset binnen een array of object. En als er één les was uit het fiasco van 32-naar-64-bits migratie, dan was het om specifiek te zijn over welke eigenschappen een type moest hebben, en niet om er een te gebruiken die verschillende dingen betekende in verschillende programma’s.


Antwoord 8, autoriteit 2%

size_ten intzijn niet uitwisselbaar. Op 64-bit Linux is size_tbijvoorbeeld 64-bit (dwz sizeof(void*)) maar intis 32-bit.

Houd er rekening mee dat size_tniet ondertekend is. Als je een ondertekende versie nodig hebt, dan is er op sommige platforms ssize_ten dit zou relevanter zijn voor jouw voorbeeld.

Als algemene regel raad ik aan om intte gebruiken voor de meeste algemene gevallen en alleen size_t/ssize_tte gebruiken als er een specifieke behoefte is aan it (met bijvoorbeeld mmap()).


Antwoord 9, autoriteit 2%

size_tis een niet-ondertekend geheel getal gegevenstype dat alleen 0 en groter dan 0 gehele getallen kan toewijzen. Het meet bytes van de grootte van elk object en wordt geretourneerd door de operator sizeof.

constis de syntaxisweergave van size_t, maar zonder constkun je het programma uitvoeren.

const size_t number;

size_twordt regelmatig gebruikt voor array-indexering en lustelling. Als de compiler 32-bitis, zou deze werken op unsigned int. Als de compiler 64-bitis, zou deze ook werken op unsigned long long int. Er is een maximale grootte van size_t, afhankelijk van het type compiler.

size_tal gedefinieerd in het <stdio.h>headerbestand, maar het kan ook worden gedefinieerd door de
<stddef.h>, <stdlib.h>, <string.h>, <time.h>en <wchar.h>koppen.

Voorbeeld (met const)

#include <stdio.h>
int main()
{
    const size_t value = 200;
    size_t i;
    int arr[value];
    for (i = 0 ; i < value ; ++i)
    {
        arr[i] = i;
    }
    size_t size = sizeof(arr);
    printf("size = %zu\n", size);
}

Uitvoer:size = 800


Voorbeeld (zonder const)

#include <stdio.h>
int main()
{
    size_t value = 200;
    size_t i;
    int arr[value];
    for (i = 0; i < value; ++i)
    {
        arr[i] = i;
    }
    size_t size = sizeof(arr);
    printf("size = %zu\n", size);
}

Uitvoer:size = 800


Antwoord 10

Als je begint bij 0 en omhoog gaat, gebruik dan in het algemeen altijd een niet-ondertekend type om te voorkomen dat een overflow je in een negatieve waardesituatie brengt. Dit is van cruciaal belang, want als je arraygrenzen kleiner zijn dan het maximum van je lus, maar je lusmaximum is groter dan het maximum van je type, dan zul je negatief worden en kun je een segmentatiefout(SIGSEGV). Gebruik dus in het algemeen nooit int voor een lus die begint bij 0 en omhoog gaat. Gebruik een niet-ondertekend.


Antwoord 11

size_t is een niet-ondertekend geheel getal gegevenstype. Op systemen die de GNU C-bibliotheek gebruiken, is dit unsigned int of unsigned long int. size_t wordt vaak gebruikt voor array-indexering en lustelling.


Antwoord 12

size_tof elk niet-ondertekend type kan worden gebruikt als lusvariabele, aangezien lusvariabelen doorgaans groter dan of gelijk zijn aan 0.

Als we een size_tobject gebruiken, moeten we ervoor zorgen dat we in alle contexten, inclusief rekenkunde, alleen niet-negatieve waarden willen. Het volgende programma zou bijvoorbeeld zeker het onverwachte resultaat geven:

// C program to demonstrate that size_t or
// any unsigned int type should be used 
// carefully when used in a loop
#include<stdio.h>
int main()
{
const size_t N = 10;
int a[N];
// This is fine
for (size_t n = 0; n < N; ++n)
a[n] = n;
// But reverse cycles are tricky for unsigned 
// types as can lead to infinite loop
for (size_t n = N-1; n >= 0; --n)
printf("%d ", a[n]);
}
Output
Infinite loop and then segmentation fault

Antwoord 13

Dit is een platformspecifieke typedef. Op een bepaalde computer kan het bijvoorbeeld unsigned intof unsigned longzijn. U moet deze definitie gebruiken voor meer draagbaarheid van uw code.


Antwoord 14

Voor zover ik weet, is size_teen unsignedinteger waarvan de bitgrootte groot genoeg is om een pointer van de oorspronkelijke architectuur te bevatten.

Dus:

sizeof(size_t) >= sizeof(void*)

Other episodes