Movatterモバイル変換


[0]ホーム

URL:


cppreference.com
Namespaces
Variants
    Actions

      Array declaration

      From cppreference.com
      <c‎ |language
       
       
       
       

      Array is a type consisting of a contiguously allocated nonempty sequence of objects with aparticularelement type. The number of those objects (the array size) never changes during the array lifetime.

      Contents

      [edit]Syntax

      In thedeclaration grammar of an array declaration, thetype-specifier sequence designates theelement type (which must be a complete object type), and thedeclarator has the form:

      [static(optional)qualifiers (optional)expression (optional)]attr-spec-seq (optional) (1)
      [qualifiers (optional)static(optional)expression (optional)]attr-spec-seq (optional) (2)
      [qualifiers (optional)*]attr-spec-seq (optional) (3)
      1,2) General array declarator syntax
      3) Declarator for VLA of unspecified size (can appear in function prototype scope only)where
      expression - any expression other thancomma operator, designates the number of elements in the array
      qualifiers - any combination ofconst,restrict, orvolatile qualifiers, only allowed in function parameter lists; this qualifies the pointer type to which this array parameter is transformed
      attr-spec-seq -(C23)optional list ofattributes, applied to the declared array
      float fa[11],*afp[17];// fa is an array of 11 floats// afp is an array of 17 pointers to floats

      [edit]Explanation

      There are several variations of array types: arrays of known constant size, variable-length arrays, and arrays of unknown size.

      [edit]Arrays of constant known size

      Ifexpression in an array declarator is aninteger constant expression with a value greater than zeroand the element type is a type with a known constant size (that is, elements are not VLA)(since C99), then the declarator declares an array of constant known size:

      int n[10];// integer constants are constant expressionschar o[sizeof(double)];// sizeof is a constant expressionenum{ MAX_SZ=100};int n[MAX_SZ];// enum constants are constant expressions

      Arrays of constant known size can usearray initializers to provide their initial values:

      int a[5]={1,2,3};// declares int[5] initialized to 1,2,3,0,0char str[]="abc";// declares char[4] initialized to 'a','b','c','\0'

      In function parameter lists, additional syntax elements are allowed within the array declarators: the keywordstatic andqualifiers, which may appear in any order before the size expression (they may also appear even when the size expression is omitted).

      In eachfunction call to a function where an array parameter uses the keywordstatic between[ and], the value of the actual parameter must be a valid pointer to the first element of an array with at least as many elements as specified byexpression:

      void fadd(double a[static10],constdouble b[static10]){for(int i=0; i<10; i++){if(a[i]<0.0)return;        a[i]+= b[i];}}// a call to fadd may perform compile-time bounds checking// and also permits optimizations such as prefetching 10 doublesint main(void){double a[10]={0}, b[20]={0};    fadd(a, b);// OKdouble x[5]={0};    fadd(x, b);// undefined behavior: array argument is too small}

      Ifqualifiers are present, they qualify the pointer type to which the array parameter type is transformed:

      int f(constint a[20]){// in this function, a has type const int* (pointer to const int)}int g(constint a[const20]){// in this function, a has type const int* const (const pointer to const int)}

      This is commonly used with therestrict type qualifier:

      void fadd(double a[staticrestrict10],constdouble b[staticrestrict10]){for(int i=0; i<10; i++)// loop can be unrolled and reordered{if(a[i]<0.0)break;        a[i]+= b[i];}}

      Variable-length arrays

      Ifexpression is not aninteger constant expression, the declarator is for an array of variable size.

      Each time the flow of control passes over the declaration,expression is evaluated (and it must always evaluate to a value greater than zero), and the array is allocated (correspondingly,lifetime of a VLA ends when the declaration goes out of scope). The size of each VLA instance does not change during its lifetime, but on another pass over the same code, it may be allocated with a different size.

      Run this code
      #include <stdio.h> int main(void){int n=1;label:;int a[n];// re-allocated 10 times, each with a different sizeprintf("The array has %zu elements\n",sizeof a/sizeof*a);if(n++<10)goto label;// leaving the scope of a VLA ends its lifetime}

      If the size is*, the declaration is for a VLA of unspecified size. Such declaration may only appear in a function prototype scope, and declares an array of a complete type. In fact, all VLA declarators in function prototype scope are treated as ifexpression were replaced by*.

      void foo(size_t x,int a[*]);void foo(size_t x,int a[x]){printf("%zu\n",sizeof a);// same as sizeof(int*)}

      Variable-length arrays and the types derived from them (pointers to them, etc) are commonly known as "variably-modified types" (VM). Objects of any variably-modified type may only be declared at block scope or function prototype scope.

      externint n;int A[n];// Error: file scope VLAexternint(*p2)[n];// Error: file scope VMint B[100];// OK: file-scope array of constant known sizevoid fvla(int m,int C[m][m]);// OK: prototype-scope VLA

      VLA must have automatic or allocated storage duration. Pointers to VLA, but not VLA themselves may also have static storage duration. No VM type may have linkage.

      void fvla(int m,int C[m][m])// OK: block scope/auto duration pointer to VLA{typedefint VLA[m][m];// OK: block scope VLAint D[m];// OK: block scope/auto duration VLA//  static int E[m]; // Error: static duration VLA//  extern int F[m]; // Error: VLA with linkageint(*s)[m];// OK: block scope/auto duration VM    s=malloc(m*sizeof(int));// OK: s points to VLA in allocated storage//  extern int (*r)[m]; // Error: VM with linkagestaticint(*q)[m]=&B;// OK: block scope/static duration VM}}

      Variably-modified types cannot be members of structs or unions.

      struct tag{int z[n];// Error: VLA struct memberint(*y)[n];// Error: VM struct member};
      (since C99)

      If the compiler defines the macro constant__STDC_NO_VLA__ to integer constant1, then VLA and VM types are not supported.

      (since C11)
      (until C23)

      If the compiler defines the macro constant__STDC_NO_VLA__ to integer constant1, then VLA objects with automatic storage duration are not supported.

      The support for VM types and VLAs with allocated storage durations is mandated.

      (since C23)

      [edit]Arrays of unknown size

      Ifexpression in an array declarator is omitted, it declares an array of unknown size. Except in function parameter lists (where such arrays are transformed to pointers) and when aninitializer is available, such type is anincomplete type (note that VLA of unspecified size, declared with* as the size, is a complete type)(since C99):

      externint x[];// the type of x is "array of unknown bound of int"int a[]={1,2,3};// the type of a is "array of 3 int"

      Within astruct definition, an array of unknown size may appear as the last member (as long as there is at least one other named member), in which case it is a special case known asflexible array member. Seestruct for details:

      struct s{int n;double d[];};// s.d is a flexible array memberstruct s*s1=malloc(sizeof(struct s)+(sizeof(double)*8));// as if d was double d[8]


      (since C99)

      [edit]Qualifiers

      If an array type is declared with aconst,volatile, orrestrict(since C99) qualifier (which is possible through the use oftypedef), the array type is not qualified, but its element type is:

      (until C23)

      An array type and its element type are always considered to be identically qualified, except that an array type is never considered to be_Atomic-qualified.

      (since C23)
      typedefint A[2][3];const A a={{4,5,6},{7,8,9}};// array of array of const intint* pi= a[0];// Error: a[0] has type const int*void* unqual_ptr= a;// OK until C23; error since C23// Notes: clang applies the rule in C++/C23 even in C89-C17 modes

      _Atomic is not allowed to be applied to an array type, although an array of atomic type is allowed.

      typedefint A[2];// _Atomic A a0 = {0};    // Error// _Atomic(A) a1 = {0};   // Error_Atomicint a2[2]={0};// OK_Atomic(int) a3[2]={0};// OK
      (since C11)

      [edit]Assignment

      Objects of array type are notmodifiable lvalues, and although their address may be taken, they cannot appear on the left hand side of an assignment operator. However, structs with array members are modifiable lvalues and can be assigned:

      int a[3]={1,2,3}, b[3]={4,5,6};int(*p)[3]=&a;// okay, address of a can be taken// a = b;            // error, a is an arraystruct{int c[3];} s1, s2={3,4,5};s1= s2;// okay: can assign structs holding array members

      [edit]Array to pointer conversion

      Anylvalue expression of array type, when used in any context other than

      (since C11)

      undergoes animplicit conversion to the pointer to its first element. The result is not an lvalue.

      If the array was declaredregister, the behavior of the program that attempts such conversion is undefined.

      int a[3]={1,2,3};int* p= a;printf("%zu\n",sizeof a);// prints size of arrayprintf("%zu\n",sizeof p);// prints size of a pointer

      When an array type is used in a function parameter list, it is transformed to the corresponding pointer type:int f(int a[2]) andint f(int* a) declare the same function. Since the function's actual parameter type is pointer type, a function call with an array argument performs array-to-pointer conversion; the size of the argument array is not available to the called function and must be passed explicitly:

      Run this code
      #include <stdio.h> void f(int a[],int sz)// actually declares void f(int* a, int sz){for(int i=0; i< sz;++i)printf("%d\n", a[i]);} void g(int(*a)[10])// pointer to array parameter is not transformed{for(int i=0; i<10;++i)printf("%d\n",(*a)[i]);} int main(void){int a[10]={0};    f(a,10);// converts a to int*, passes the pointer    g(&a);// passes a pointer to the array (no need to pass the size)}

      [edit]Multidimensional arrays

      When the element type of an array is another array, it is said that the array is multidimensional:

      // array of 2 arrays of 3 ints eachint a[2][3]={{1,2,3},// can be viewed as a 2x3 matrix{4,5,6}};// with row-major layout

      Note that when array-to-pointer conversion is applied, a multidimensional array is converted to a pointer to its first element, e.g., pointer to the first row:

      int a[2][3];// 2x3 matrixint(*p1)[3]= a;// pointer to the first 3-element rowint b[3][3][3];// 3x3x3 cubeint(*p2)[3][3]= b;// pointer to the first 3x3 plane

      Multidimensional arrays may be variably modified in every dimension if VLAs are supported(since C11):

      int n=10;int a[n][2*n];
      (since C99)

      [edit]Notes

      Zero-length array declarations are not allowed, even though some compilers offer them as extensions (typically as a pre-C99 implementation offlexible array members).

      If the sizeexpression of a VLA has side effects, they are guaranteed to be produced except when it is a part of a sizeof expression whose result doesn't depend on it:

      int n=5, m=5;size_t sz=sizeof(int(*[n++])[m++]);// n is incremented, m may or may not be incremented

      [edit]References

      • C23 standard (ISO/IEC 9899:2024):
      • 6.7.6.2 Array declarators (p: TBD)
      • C17 standard (ISO/IEC 9899:2018):
      • 6.7.6.2 Array declarators (p: 94-96)
      • C11 standard (ISO/IEC 9899:2011):
      • 6.7.6.2 Array declarators (p: 130-132)
      • C99 standard (ISO/IEC 9899:1999):
      • 6.7.5.2 Array declarators (p: 116-118)
      • C89/C90 standard (ISO/IEC 9899:1990):
      • 3.5.4.2 Array declarators

      [edit]See also

      C++ documentation forArray declaration
      Retrieved from "https://en.cppreference.com/mwiki/index.php?title=c/language/array&oldid=179987"

      [8]ページ先頭

      ©2009-2025 Movatter.jp