สำนวนนี้หลุดออกจากการจัดสรรอาร์เรย์ 1D โดยธรรมชาติ เริ่มต้นด้วยการจัดสรรอาร์เรย์ 1D ของบางประเภทโดยพลการT:
T *p = malloc( sizeof *p * N );
ง่ายใช่มั้ย? แสดงออก *pมีประเภทTเพื่อsizeof *pให้ผลเช่นเดียวsizeof (T)ดังนั้นเราจึงจัดสรรพื้นที่เพียงพอสำหรับอาร์เรย์องค์ประกอบของN Tนี้เป็นจริงสำหรับประเภทใด   ๆT
ตอนนี้ให้แทนของกับชนิดอาร์เรย์เช่นT R [10]จากนั้นการจัดสรรของเราจะกลายเป็น
R (*p)[10] = malloc( sizeof *p * N);
ความหมายตรงนี้เหมือนกับวิธีการจัดสรร 1D สิ่งที่เปลี่ยนไปคือประเภทของp. แทนที่จะก็ตอนนี้T * R (*)[10]การแสดงออกที่*pมีประเภทTซึ่งเป็นประเภทR [10]เพื่อให้sizeof *pเทียบเท่ากับซึ่งเทียบเท่ากับsizeof (T) sizeof (R [10])ดังนั้นเรากำลังการจัดสรรพื้นที่เพียงพอสำหรับNโดยอาร์เรย์องค์ประกอบของ  10R
เราสามารถนำสิ่งนี้ไปได้ไกลกว่านี้ถ้าเราต้องการ สมมติว่าเป็นตัวเองชนิดอาร์เรย์R int [5]แทนสิ่งนั้นRและเราได้รับ
int (*p)[10][5] = malloc( sizeof *p * N);
จัดการกัน - sizeof *pเป็นเช่นเดียวกับsizeof (int [10][5])เราและเราไขลานจัดสรรก้อนที่ต่อเนื่องกันของหน่วยความจำขนาดใหญ่พอที่จะถือNโดย10โดยอาร์เรย์ของ  5int
นั่นคือด้านการจัดสรร แล้วด้านการเข้าถึงล่ะ?
โปรดจำไว้ว่า[]การดำเนินการห้อยถูกกำหนดไว้ในแง่ของการคำนวณตัวชี้: a[i]ถูกกำหนดให้เป็น1*(a + i) ดังนั้นตัวดำเนินการตัวห้อยจึงหมายถึงตัวชี้[] โดยปริยาย หากpเป็นตัวชี้ไปTคุณสามารถเข้าถึงค่าที่ชี้ไปที่ใดก็ได้โดยการยกเลิกการอ้างอิงอย่างชัดเจนด้วยตัวดำเนิน*การยูนารี:
T x = *p;
หรือโดยใช้ตัว[]ดำเนินการตัวห้อย:
T x = p[0]; // identical to *p
ดังนั้นหากpชี้ไปที่องค์ประกอบแรกของอาร์เรย์คุณสามารถเข้าถึงองค์ประกอบใด ๆ ของอาร์เรย์นั้นได้โดยใช้ตัวห้อยบนตัวชี้p:
T arr[N];
T *p = arr; // expression arr "decays" from type T [N] to T *
...
T x = p[i]; // access the i'th element of arr through pointer p
ตอนนี้เรามาทำการแทนที่ของเราอีกครั้งและแทนที่Tด้วยประเภทอาร์เรย์R [10]:
R arr[N][10];
R (*p)[10] = arr; // expression arr "decays" from type R [N][10] to R (*)[10]
...
R x = (*p)[i];
ความแตกต่างที่เห็นได้ชัดในทันที เรากำลังอ้างถึงอย่างชัดเจนpก่อนที่จะใช้ตัวดำเนินการตัวห้อย เราไม่ต้องการตัวห้อยpเราต้องการห้อยลงในสิ่งที่p ชี้ไป (ในกรณีนี้คืออาร์เรย์ arr[0] ) ตั้งแต่เอก*มีความสำคัญต่ำกว่าห้อย[]ประกอบการที่เราจะต้องใช้วงเล็บอย่างชัดเจนในกลุ่มด้วยp *แต่จำไว้ว่าจากด้านบนนั้น*pเหมือนกับp[0]เราจึงสามารถแทนที่ด้วย
R x = (p[0])[i];
หรือเพียงแค่
R x = p[0][i];
ดังนั้นหากpชี้ไปที่อาร์เรย์ 2 มิติเราสามารถจัดทำดัชนีในอาร์เรย์pนั้นได้ดังนี้:
R x = p[i][j]; // access the i'th element of arr through pointer p;
               // each arr[i] is a 10-element array of R
นำสิ่งนี้ไปสู่ข้อสรุปเดียวกันกับด้านบนและแทนที่Rด้วยint [5]:
int arr[N][10][5];
int (*p)[10][5]; // expression arr "decays" from type int [N][5][10] to int (*)[10][5]
...
int x = p[i][j][k];
นี้ทำงานเพียงเดียวกันถ้าชี้ไปยังอาร์เรย์ปกติหรือถ้ามันชี้ไปจัดสรรหน่วยความจำผ่าน  pmalloc
สำนวนนี้มีประโยชน์ดังต่อไปนี้:
- มันง่ายมาก - โค้ดเพียงบรรทัดเดียวซึ่งต่างจากวิธีการจัดสรรทีละน้อยT **arr = malloc( sizeof *arr * N );
if ( arr )
{
  for ( size_t i = 0; i < N; i++ )
  {
    arr[i] = malloc( sizeof *arr[i] * M );
  }
}
 
- แถวทั้งหมดของอาร์เรย์ที่จัดสรรคือ * ต่อเนื่องกัน * ซึ่งไม่ใช่กรณีของวิธีการจัดสรรทีละน้อยข้างต้น
- deallocating freeอาร์เรย์เป็นเพียงเป็นเรื่องง่ายด้วยสายเดียวที่จะ อีกครั้งไม่เป็นความจริงกับวิธีการจัดสรรทีละน้อยซึ่งคุณต้องยกเลิกการจัดสรรแต่ละรายการarr[i]ก่อนจึงจะสามารถยกเลิกการจัดสรรarrได้
บางครั้งวิธีการจัดสรรแบบทีละชิ้นจะดีกว่าเช่นเมื่อฮีปของคุณแยกส่วนไม่ดีและคุณไม่สามารถจัดสรรหน่วยความจำของคุณเป็นชิ้นส่วนที่ต่อเนื่องกันได้หรือคุณต้องการจัดสรรอาร์เรย์แบบ "หยัก" ซึ่งแต่ละแถวสามารถมีความยาวต่างกันได้ แต่โดยทั่วไปแล้วนี่เป็นวิธีที่ดีกว่า  
1. โปรดจำไว้ว่าอาร์เรย์ไม่ใช่ตัวชี้ แต่นิพจน์อาร์เรย์จะถูกแปลงเป็นนิพจน์พอยน์เตอร์ตามความจำเป็น