Cú pháp ngôn ngữ C

Cú pháp ngôn ngữ (lập trình) C là tập hợp các quy tắc nhằm xác định cách thức để viết và dịch trong ngôn ngữ lập trình C.
Các hàm.
Cú pháp.
Một hàm C phải bao gồm một kiểu trả về (kiểu đó trả về codice_1 nếu không có giá trị trả về), một tên xác định, một danh sách các tham số để trong ngoặc đơn (nếu danh sách này không có tham số nào thì ghi là codice_1 bên trong dấu ngoặc), sau đó là khối các câu lệnh (hay khối mã) và/hay các câu lệnh codice_3. (Nếu kiểu trả về là codice_1 thì mệnh đề này không bắt buộc phải có. Ngược lại, cũng không bắt buộc chỉ có một câu lệnh codice_3 mà tùy theo kỹ thuật, người lập trình có thể dẫn dòng mã sao cho mọi hướng chẻ nhánh đều được trả về đúng kiểu.)
Trong đó, codice_6 của codice_7 biến thì được khai báo như là kiểu dữ liệu và tách rời nhau bởi dấu phẩy codice_8:
Toàn bộ danh sách này được đặt trong ngoặc đơn ngay sau tên_hàm.
Thí dụ.
Hàm codice_9 tính tổng hai số có kiểu integer, hàm codice_10 tính trị tuyệt đối của số có kiểu integer, và chương trình (hàm main) hiển thị hai dòng codice_11 và codice_12
Chú ý: phần mã trên đã được thử thành công dùng trình dịch GNU (cho ANSI C và C99)
Mô tả.
Trong các câu lệnh tiền xử lý, ở cấp độ cao nhất, một chương trình ngôn ngữ C luôn có một chuỗi các khai báo cho các tập tin bao gồm.
Sau đó là các khai báo của phạm vi tập tin. Các khai báo này giới thiệu các hàm, các biến và các kiểu biến. Các hàm trong C nhìn tương tự với các chương trình con của Fortran hay các thủ tục của Pascal. Định nghĩa của hàm xuất hiện trong phần thân của nó (phần giữa bộ dấu ngoặc codice_13 và codice_14 theo sau nguyên dạng của hàm).
Các chương trình trong C để tạo các ứng dụng trực tiếp đều cần phải có một hàm đặc biệt tên là codice_15, đây sẽ là hàm đầu tiên được gọi khi chương trình bắt đầu thực thi. Sau đây là một chương trình đầy đủ mặc dù không có mấy ứng đụng thiết thực.
 int main (void)
 return 0;
Hàm code&gt;main&lt;/code&gt; thường gọi các hàm khác để giúp nó hoàn tất công việc (tuỳ theo sự lập trình của người dùng).
Trọng một số trường hợp C được dùng không phải để tạo ra các ứng dụng trực tiếp mà để dùng với hệ điều hành hay các nơi khác (như là phát triển các bộ điều vận, các phần sụn, hay các thư viện...). Những trường hợp như vậy thì người lập trình hoàn toàn tự do trong việc giải quyết làm sao để xử lý khởi động chương trình, đặc biệt nó sẽ không cần định nghĩa hàm codice_15.
Các hàm có thể được viết ra bởi người lập trình hay được cung cấp sẵn bởi các thư viện. Các thư viện cần được khai báo (sử dụng) bằng cách nêu tên các tập tin tiêu dề trong câu lệnh dạng codice_17. Một số hàm thư viện như là codice_18 đã được định nghĩa bởi chuẩn C, chúng được tham chiếu như là các hàm thư viện chuẩn.
Một hàm có thể trả về một giá trị cho môi trường gọi nó. Khi hàm codice_15 trả về giá trị 0 chỉ dấu cho rằng toàn bộ chương trình đã hoàn tất thành công và kết thúc. Hàm codice_18 cùng có giá trị trả về, đó là số lượng ký tự đã hiển thị, nhưng giá trị này thường bị bỏ qua không dùng.
Truyền các biến.
Các biến trong C được truyền qua các hàm "bằng giá trị" trong khi nhiều ngôn ngữ khác lại được truyền "bằng tham chiếu" (hay bằng địa chỉ). Điều này có nghĩa là hàm chỉ chép lại các giá trị và không thể thay đổi các giá trị đó của các biến (hay đối số) đưa vào. Để có thể thay đổi được giá trị của các biến truyền vào, người lập trình có thể truyền địa chỉ của nó vào hàm và tham chiếu ngược nó trong hàm được dùng (xem thêm kiểu tham chiếu)
Để có thể chuyển một con trỏ (mà có thể cần đổi địa chỉ nó chỉ đến), có thể chuyển một tham chiếu cho con trỏ (tham chiếu này chỉ đến địa chỉ của con trỏ):
codice_21 sẽ định nghĩa một con trỏ chỉ đến con trỏ (thay vì chỉ đến các kiểu dữ liệu thông thường) tức là chỉ đến địa chỉ của con trỏ codice_22.
Hàm scanf làm việc theo cùng một cách thức:
Các cấu trúc dòng điều khiển.
Một cách cơ bản thì C là ngôn ngữ dạng tự do. Trong phần này, tất cả các chữ "mệnh đề" có nghĩa tương đương với chữ "câu lệnh".
Các mệnh đề phức hợp.
Câu lệnh phức hợp được bọc trong dấu ngoặc codice_13 và codice_14 còn được gọi là khối mã. Các câu lệnh phức hợp trong C có dạng.
Khối mã được dùng như là phần thân của một hàm hay được đặt bất kì ở vị trí nào mà một câu lệnh đơn giản có thể đặt. Nghĩa là, về ý nghĩa văn phạm thì câu lệnh đơn giản và câu lệnh phức hợp là tương đương nhau.
Các mệnh đề biểu thức.
Một câu lệnh (hay một mệnh đề) của C có dạng:
 &lt;biểu thức tùy chọn&gt;;
là một mệnh đề biểu thức. Nếu biểu thức này không có nội dung (mà chỉ còn lại dấu codice_25 thì biểu thức được gọi là codice_26 (hay mệnh dề rỗng). (Theo ngôn ngữ máy Assembler thì mệnh đề null sẽ tương đương với câu lệnh NOP; chiếm 1 byte chỉ làm nhiệm vụ tăng địa chỉ của chồng ("stack") lên 1 đơn vị.)
Các mệnh đề lựa chọn (hay điều kiện).
Có ba loại mệnh đề lựa chọn: hai loại dùng từ khóa codice_27 và một loại dùng từ khóa codice_28. Đó là:
Dạng dùng từ khóa codice_27.
 if (&lt;biểu thức&gt;)
 &lt;mệnh đề1&gt;;
 if (&lt;biểu thức&gt;)
 &lt;mệnh đề1&gt;;
 else
 &lt;mệnh đề2&gt;;
Trong dạng này, nếu phần trong ngoặc đơn có giá trị khác 0 hay có giá trị "đúng" ("true") thì dòng điều khiển sẽ chuyển vào để thực thi &lt;mệnh đề1&gt;. Nếu trong câu lệnh codice_27 có thêm từ khóa codice_31 thì &lt;mệnh đề2&gt; sẽ được thực thi một khi &lt;biểu thức&gt; có giá trị 0 hay giá trị "sai".
Nhắc lại: như trên thì vị trí mỗi mệnh đề đều có thể thay bằng một khối mã.
Trong cách viết mã lồng nhau phức tạp bao gồm nhiều mệnh đề codice_27 thì từ khóa codice_31 sẽ được gán vào mệnh đề codice_27 phía trên gần nhất nào chưa được ghép. Để tránh sự nhầm lẫn cách tốt nhất là lồng chúng vào trong các dấu codice_13 và codice_14.
Dạng dùng từ khóa codice_28.
Mệnh đề codice_28 sẽ gây ra việc chuyển dòng điều khiển sang một trong những mệnh đề con kế tiếp tùy theo giá trị của một biểu thức X (biểu thức này phải có kiểu nguyên). Các mệnh đề con này thường là các mệnh đề phức hợp. Đứng trước mỗi mệnh đề con sẽ là một từ khóa codice_39, sau đó là một biểu thức hằng Hi, và dấu hai chấm codice_40 gắn liền tiếp theo đó là mệnh đề con Mi.
Khi giá trị của X trùng với một giá trị Hi được nêu ở đâu thì mệnh đề con đi gắn liền với hằng tại đó (tức là Mi) sẽ được thực thi.
Nếu X không bằng với bất kì giá trị Hi nào thì người lập trình có thể dùng thêm từ khóa codice_41, sau đó là dấu hai chấm codice_40 và tiếp theo là một mệnh đề con Mdefault. Mệnh đề con này sẽ được thực thi khi mà giá trị của X khác với mọi giá trị hằng Hi.
Lưu ý:
Trong dạng thí dụ dưới đây, nếu &lt;biểu thức X&gt; có giá trị bằng &lt;hằng H2&gt; thì mệnh đề các biểu thức &lt;mệnh đề M2&gt;,&lt;mệnh đề M3&gt;, và &lt;mệnh đề Mdefault&gt; sẽ lần lần lượt được thực thi theo thứ tự nếu như trong chúng không có câu lệnh codice_48. Nhưng vì trong mã thí dụ có câu lệnh codice_48 nên dòng điều khiển sẽ ngưng và kết thúc câu lệnh codice_28 khi thi hành lệnh codice_48 này.
 switch (&lt;biểu thức X&gt;)
 case &lt;hằng H1&gt;: &lt;BR&gt;
 &lt;mệnh đề M1&gt; &lt;BR&gt;
 case &lt;hằng H2&gt;:&lt;BR&gt;
 &lt;mệnh đề M2&gt; &lt;BR&gt;
 break;&lt;BR&gt;
 case &lt;hằng H3&gt;:&lt;BR&gt;
 &lt;mệnh đề M3&gt;&lt;BR&gt;
 default:&lt;BR&gt;
 &lt;mệnh đề Mdefault&gt; &lt;BR&gt;
Các mệnh đề tái lặp (hay vòng lặp).
C có 3 dạng câu lệnh vòng lặp:
Vòng lặp codice_53.
 do
 &lt;mệnh đề&gt;
 while (&lt;biểu thức&gt;);
Trong mệnh đề này thì mệnh đề được thực thi lặp lại cho tới khi nào &lt;biểu thức&gt; được đánh giá (hay có giá trị) là codice_54. Một khi &lt;biểu thức&gt; không còn có giá trị codice_54 nữa thì vòng lặp sẽ bị kết thúc.
Vòng lặp codice_56.
 while (&lt;biểu thức&gt;)
 &lt;mệnh đề&gt;
&lt;mệnh đề&gt; chỉ được thực thi hay thực thi lặp lại khi &lt;biểu thức&gt; có giá trị là codice_54. Nếu &lt;biểu thức&gt; có giá trị codice_58 thì câu lệnh sẽ bị kết thúc ngay lập tức.
Vòng lặp codice_59.
Dạng C89 của vòng lặp codice_59 là:
 for (&lt;biểu thức 1&gt;; &lt;biểu thức 2&gt;; &lt;biểu thức 3&gt;)
 &lt;câu lệnh&gt;
Nó đã được tổng quát hóa trong C99 thành:
 for (&lt;khai báo&gt; &lt;biểu thức 1&gt;; &lt;biểu thức 2&gt;)
 &lt;câu lệnh&gt;
Khi cả ba biểu thức đều hiện diện trong một câu lệnh codice_59, thì mệnh đề:
 for (e1; e2; e3)
 s;
sẽ tương đương với
 e1;
 while (e2) {
 s;
 e3;
Bất kì biểu thức nào trong vòng lặp codice_59 có thể được loại bỏ. Một biểu thức bị mất (e2 chẳng hạn) có thể làm cho vòng lặp biến thành vòng lặp vô hạn.
 for (x=10,y=1;((x&gt;4) &amp;&amp; (y&lt;8)); x--,y+=2)
 printf("x = %d, y = %d \n", x,y);
Kết quả thực thi màn hình sẽ hiển thị như sau:
 x = 10, y = 1
 x = 9, y = 3
 x = 8, y = 5
 x = 7, y = 7
Vòng lặp kết thúc vì điều kiện trong biểu thức thứ nhì ((x&gt;4) &amp;&amp; (y&lt;8)) không còn đúng nữa.
Các mệnh đề nhảy (hay bước nhảy).
Các lệnh nhảy sẽ thay đổi dòng điều khiển một cách vô điều kiện. có 4 kiểu mệnh đề nhảy trong C là codice_65, codice_66, codice_48, và codice_3.
codice_65.
câu lệnh codice_65 sẽ có dạng:
 goto &lt;nhãn&gt;;
nhãn phải có mặt trong hàm có chứa câu lệnh codice_65. Khi đọc đến lệnh này, dòng điều khiển sẽ chuyển đến mệnh đề nhãn.
codice_66.
Mệnh đề codice_66 chỉ có thể xuất hiện trong một vòng lặp và có tác dụng làm cho dòng điều khiển chuyển sang chu kì mới của vòng lặp trong cùng nhất (có chứa câu lệnh). Các dạng sử dụng bao gồm
 while (expression) {
 cont:;
 do {
 cont:;
 } while (expression);
 for (optional-expr; optexp2; optexp3) {
 cont:;
codice_48.
Mệnh đề codice_48 dùng để kết thúc một câu lệnh vòng lặp hay câu lệnh codice_28 ngay lập tức và chuyển tiếp đến câu lệnh tiếp theo sau của vòng lặp đó.
codice_3.
Một hàm trả dòng điều khiển về nơi gọi nó bằng câu lệnh codice_3. Khi lệnh codice_3 được theo sau bởi một biểu thức thì biểu thức đó sẽ được đánh giá và giá trị này sẽ được trả về cho nơi đã gọi hàm. Khi return được gọi mà không có biểu thức đi kèm thì giá trị trả về là không xác định.
Các phép toán.
"Xem thêm bài chính" Phép toán trong C và C++
Để tham khảo, sau đây là bảng thứ tự ưu tiên của các phép toán theo C89:
Nguồn: C Operator Precedence and Associativity
Khai báo dữ liệu.
Các kiểu dữ liệu cơ bản.
Nhiều ngôn ngữ lập trình kể cả C, biểu thị các số trong hai dạng: nguyên và thực (hay không nguyên). Sự khác nhau này hình thành từ khía cạnh kỹ thuật của các cách thức xử lý và lưu trữ các giá trị trong bộ nhớ.
Kiểu nguyên viết dưới dạng codice_80 được dùng để biểu thị các số nguyên. Kiểu nguyên có trong nhiều kích cỡ khác nhau tùy theo phân lượng bộ nhớ được dùng và độ lớn cao nhất. Các từ khóa, có tên là các định tính, được dùng thêm vào để điều chỉnh lại kích cỡ là: codice_81, codice_82 và codice_83. Kiểu ký tự mà từ khóa của nó là codice_84, biểu thị đơn vị nhỏ nhất có thể địa chỉ hóa được (bởi kiến trúc máy tính) thường là một byte với 8 bit.
Dạng thực được dùng để biểu thị các số thập phân hay các bộ phận hữu tỉ. Mặc dù vậy chúng không hoàn toàn chính xác mà chỉ là các biểu thị gần đúng.
Có 3 kiểu giá trị thực bao gồm: loại có độ chính xác đơn (có đặc tả là codice_85), loại có độ chính xác kép (có đặc tả là codice_86), và loại có độ chính xác kép mở rộng (có đặc tả là codice_87). Mỗi loại dùng để biểu thị các giá trị không nguyên trong một dạng khác nhau.
Các kiểu nguyên có thể hoặc là có dấu (codice_88) hay không dấu (codice_89). Nếu không chỉ rõ khi khai báo thì mặc định (hiểu ngầm) sẽ là loại có dấu. Một ngoại lệ là các kiểu codice_84, codice_91 và codice_92 đều khác nhau, và kiểu codice_84 có thể là loại có dấu hay không có dấu.
Đối với loại có dấu, thì codice_94 có nghĩa cao nhất được dùng để biểu thị dấu (dương hay âm). Thí dụ một số nguyên 16-bit loại có dấu thì chỉ dùng 15 bit để biểu thị giá trị (tuyệt đối) của nó còn bit có nghĩa cao nhất lại được dùng để cho biết đó là số dương hay âm. Đối với loại không dấu thì bit này lại được dùng thêm vào để biểu thị giá trị.
Các hằng số xác định các giá trị biên.
Tập tin tiêu đề chuẩn codice_95 sẽ xác định các giá trị nhỏ nhất và lớn nhất của các kiểu nguyên cơ bản cũng như là xác định các giới hạn khác. Tập tin tiêu đề chuẩn codice_96 sẽ xác định các giá trị nhỏ nhất và lớn nhất của các kiểu codice_85, codice_86, và codice_87. Nó cũng xác định các giới hạn khác liên quan tới việc xử lý các giá trị của dấu chấm động ("floating-point") có độ chính xác đơn hay có độ chính xác kép như là chúng được định nghĩa trong chuẩn IEEE 754.
Các giá trị biên điển hình.
Sau đây là danh sách kích cỡ và các biên "điển hình" của các kiểu nguyên. Các giá trị này có thể khác nhau tùy theo kiến trúc (máy và trình dịch). ISO C cung cấp tiêu đề inttypes.h, trong đó, có xác định các kiểu nguyên có dấu và không có dấu nhưng điều chắc chắn là kích cỡ đều nằm trong khoảng 8 đến 64 bit.
Kích cỡ và giới hạn của kiểu cơ bản codice_80 (mà không có các định tính codice_81, codice_82, hay codice_83) có thể thay đổi khác nhau (nhiều hơn các kiểu nguyên khác) tùy theo sư thiết lập (của trình dịch hay của kiến trúc máy). Cho nên, một thao tác thông thường là định nghĩa nó như là một "đồng nghĩa" của codice_104 — trong tập tin codice_105 — và do đó, đủ sức để thích ứng với giá trị lớn nhất khả dĩ của con trỏ mà có thể được cấp phát bởi hệ thống. Đặc tả UNIX đơn chỉ ra rằng kiểu codice_80 phải có ít nhất 32 bit, mặc dù chuẩn ISO C chỉ yêu cầu có 16 bit.
Các kiểu tham chiếu.
Tiền tố ký tự codice_107 được dùng để biểu thị kiểu tham chiếu, mà thường được biết đến như là một con trỏ. Nếu như đặc tả codice_80 biểu thị một kiểu nguyên cơ bản thì đặc tả codice_109 lại biểu thị một tham chiếu kiểu nguyên, tức là một loại con trỏ. Các giá trị tham chiếu tương quan sẽ bao gồm hai phần thông tin: đó là địa chỉ của vùng nhớ và một kiểu dữ liệu. Câu lệnh sau đây khai báo một biến tham chiếu nguyên có tên là codice_110:
Sự tham chiếu.
Khi một con trỏ địa phương được khai báo, thì chưa có một địa chỉ nào gán cho nó cả. Địa chỉ tương quan với một con trỏ có thể được thay đổi (hay hình thành) qua phép gán. Trong thí dụ sau, biến codice_110 sẽ cài cho nó chỉ tới cùng một dữ liệu như là biến nguyên cơ bản codice_112:
Để làm được việc này, toán tử tham chiếu (hay còn gọi là "tham chiếu ngược") codice_113 đã được dùng tới. Nó trả về vị trí của biến trong bộ nhớ (tức là địa chỉ) hay là chỗ chứa thực thể theo sau (trong thí dụ thì thực thể đó là a). Toán tử này như là công việc nó làm thường được gọi là toán tử "địa chỉ".
Trong trường hợp tổng quát, cụm từ giá trị tham chiếu được dùng để nói về địa chỉ trong bộ nhớ của sự tham chiếu (hay tham chiếu ngược).
Sự tham chiếu ngược.
Cùng một biểu hiện, giá trị có thể đọc về từ một giá trị tham chiếu. Trong thí dụ sau, biến nguyên cơ bản codice_114 sẽ được gán đến dữ liệu mà dữ liệu đó được tham chiếu bởi codice_110:
Để hoàn tất được thao tác này, toán tử tham chiếu ngược (codice_113) đã được dùng. Nó trả về dữ liệu cơ bản. Dữ liệu này có giá trị là một tham chiếu chỉ tới (tức là một địa chỉ). Biểu thức codice_117 là một cách viết khác của giá trị 10 (gán cho b).
Việc quá tải của ký tự * có hai biểu hiện liên hệ mà có thể gây ra sự nhầm lẫn. Hiểu được sự khác nhau giữa việc dùng nó như là một tiền tố trong một khai báo (con trỏ) và việc xem nó là toán tử tham chiếu trong một biểu thức là rất quan trọng.
Sự tham chiếu tương đương và các mệnh đề cơ bản.
Bảng sau đây là danh sách các mệnh đề tương đương giữa kiểu cơ bản và kiểu tham chiếu (hay tham chiếu ngược). Trong đó, biến cơ bản codice_118 và biến tham chiếu codice_110 được hiểu ngầm.
Các mảng.
Khai báo mảng tĩnh.
Trong C, mảng được dùng để biểu thị một cấu trúc của một dãy nhiều giá trị có cùng một kiểu được xếp thứ tự. Một mảng gọi là tĩnh nếu độ dài của dãy mảng này cố định. Sự khai báo của mảng tĩnh có cú pháp sau:
trong đó, tên của mảng là codice_120 sẽ có thể chứa được n giá trị của kiểu cơ bản codice_80. Trong thực hành, phần bộ nhớ cho n giá trị nguyên này được để dành riêng và được gán cho mảng này (mặc dù giá trị của các phần tử trong mảng chưa được xác định). Biến codice_120 thực chất là một kiểu tham chiếu của kiểu nguyên; nó khởi thủy sẽ chỉ tới địa chỉ của giá trị đầu tiên trong mảng.
Truy cập các phần tử.
Các giá trị của một mảng được gọi là các phần tử trong mảng.
 codice_125
Giá trị trả về của codice_125 chính là giá trị mà nó chứa ở vị trí k. Thoạt nhìn thì cú pháp của việc truy cập này trông giống như cú pháp khi mảng codice_120 được khai báo nhưng về chức năng thì hoàn toàn khác nhau.
Chỉ số bắt đầu của một mảng là 0. Như vậy, chỉ số lớn nhất của một mảng bằng tổng số các phần tử trong mảng trừ đi 1. Thí dụ mảng codice_128 có 10 phần tử thì giá trị của phần tử đầu tiên của A là codice_129 và của phần tử cuối dùng là A[9].
Bảng sau đây sẽ minh họa cách dùng của cả hai phương pháp:
Các mảng động.
C không cung cấp phương tiện để "kiểm tra biên" cho các mảng. Nghĩa là nó không thể bắt được các lỗi khi gán cho một mảng chỉ số âm hay chỉ số vượt quá độ đài của mảng đó. Và hơn thế nữa các chỉ số trong một mảng có thể vượt khỏi độ dài sẵn có của mảng đó.
Vì các mảng là "thuần nhất", tức là nó chỉ chứa các dữ liệu có chung một kiểu nên hai thành phần thông tin cần nhớ là địa chỉ của phần tử đầu tiên và kiểu của dữ liệu.
Nhắc lại về cú pháp để khai báo một mảng tĩnh, tức là tạo ra một biến tham chiếu nguyên và cấp phát một vùng nhớ tương ứng cho nó:
Cách biểu hiện này có thể được tái lập với sự giúp đỡ của thư viện chuẩn C. Hàm codice_130 cung cấp một cách đơn giản để cấp phát một vùng nhớ. Hai tham số dùng đến sẽ là số lượng các phần tử và kích cỡ (độ lớn) của mỗi phần tử. Khi việc cấp phát bộ nhớ hoàn thành, codice_130 trả về một con trỏ chỉ tới phần tử đầu tiên và gán cho mọi phần tử giá trị khởi động là 0. Nếu sự cấp phát vùng nhớ không thành công (vì bộ nhớ không đủ chỗ trống hạn) thì codice_130 trả về con trỏ rỗng. Thí dụ: đoạn mã sau đây có chức năng tương đương với việc khai báo một mảng tĩnh của n phần tử có kiểu codice_80:
Tuy nhiên, điểm vượt trội của cách khai báo này là việc sử dụng "cấp phát vùng nhớ động ". Kích cỡ của mảng (tức là lượng không gian nhớ được cấp phát một cách an toàn cho mảng) lại có thể được thay đổi sau khi đã khai báo.
Một khi việc cấp phát vùng nhớ động không còn cần thiết nữa thì phần bộ nhớ đó nên được trả về cho hệ điều hành. Thao tác này có thể tiến hành bằng hàm codice_134. Nó cần một tham số: tên của con trỏ mà trước đây đã xin cấp phát vùng nhớ. Một cách an toàn hơn là sau khi đã trả vùng nhớ về cho hệ điều hành, người lập trình cũng nên cài (hay gán) cho con trỏ liên đới giá trị codice_135 để hủy bỏ địa chỉ mà nó đang chỉ tới (nhằm tránh gây ra các hiệu ứng phụ do việc tham chiếu của con trỏ này có thể gây ra).
Các mảng đa chiều.
C có hỗ trợ việc dùng mảng đa chiều. Việc định nghĩa chúng giống như là tạo ra "mảng của các mảng ", mặc dù vậy trong thực tế nó không hoàn toàn đúng. Cú pháp sau:
sẽ định nghĩa một mảng hai chiều; chiều thứ nhất có codice_136 phần tử. Chiều thứ hai sẽ có codice_137 các phần tử—một tập hợp của codice_138 các phần tử mà mỗi phần tử là một chiều thứ nhất.
Các mảng đa chiều hoàn toàn có thể được xem như là dãy của các con trỏ. Trong thí dụ trên, codice_139 (nếu codice_136 là 1) sẽ là một tham chiếu giá trị nguyên mà nó chỉ tới một mảng của codice_138 các phần tử.
Dãy ký tự.
Dãy ký tự có thể được thay đổi nội dung của nó mà không cần đến thư viện chuẩn. Tuy nhiên, thư viện này có nhiều hàm có thể dùng cho cả dãy ký tự có kết thúc 0 và mảng không có ký tự kết thúc kiểu codice_84. Trong phần này từ "dãy" được để chỉ dãy ký tự.
Các hàm thường dùng là:
Các hàm ít dùng tới hơn là:
Tập tin I/O.
Trong C, I/O được tiến hành qua một nhóm các hàm trong thư viện chuẩn. Trong ANSI/ISO C, những hàm đó được định nghĩa trong codice_202.
Tiêu chuẩn I/O.
Ba tiêu chuẩn dòng I/O được định nghĩa sẵn là:
Các dòng này được tự động mở và đóng lại bởi môi trường của thời gian thi hành, chúng không cần và không nên được mở một cách rõ ràng.
Thí dụ sau minh họa làm thế nào một chương trình bộ lọc được cấu trúc một cách điển hình:
Việc chuyển các đối số qua dòng lệnh.
Các tham số được gõ vào một dòng lệnh thì được chuyển vào một chương trình C với hai biến sẵn có - một để đếm số đối số là codice_206 và biến kia là một mảng con trỏ có tên là codice_207, mà mỗi con trỏ chỉ đến một đối số (các đối số được xem như là mảng ký tự)
 myFilt p1 p2 p3
Đối với thí dụ này, các giá trị riêng lẻ của các tham số có thể được truy cập bằng codice_208, codice_209, và codice_210 như là được chỉ ra trong chương trình sau:
Thứ tự đánh giá.
Một trình dịch C có thể đánh giá các biểu thức theo thứ tự bất kì giữa dãy các điểm. Dãy các điểm được định nghĩa bởi:
Lưu ý: Các biểu thức đứng trước trong một dãy điểm sẽ luôn luôn được đánh giá trước các biểu thức theo sau. Trong trường hợp đánh giá của các ngắn mạch, biểu thức thứ hai "có thể" sẽ không cần được đánh giá. Thí dụ, trong biểu thức codice_214, nếu codice_215 trả về giá trị đúng thì trình dịch sẽ không cần đánh giá codice_216 nữa (vì lúc đó đã đủ để kết luận mệnh đề codice_214 là đúng). Trong thực hành viết mã, nhiều lập trình viên thiếu kinh nghiệm rất dễ bị lọt vào tình huống rằng trình dịch không chịu tiến hành những gì họ muốn mà bỏ qua nhiều bước dẫn tới các kết quả không chính xác mặc dù về lô gíc họ không hề sai sót. Trong trường hợp như vậy, cách tốt nhất là hãy xem lại thật kỹ các mệnh đề Bool và đặc tính đánh giá này của trình dịch. Các lỗi này thuộc loại rất khó tìm ra bởi vì nó hoàn toàn chính xác về mặt cú pháp, về mặt toán học và ngay cả về mặt thuật toán xử lý và rất dễ dẫn đến nhiều kết quả sai về mặt tính toán mà người lập trình không ngờ. Đây cũng là điểm khác nhau giữa ngôn ngữ toán học thuần túy (dùng trong các mã giả --"pseudo code ") và thực tế của ngôn ngữ lập trình.
Ứng xử không xác định.
Một khía cạnh thú vị (mặc dù chắc không đơn nhất) của tiêu chuẩn C là ứng xử của một số dạng mã chắc chắn dẫn tới tình trạng không xác định. Trong thực tế, điều này có nghĩa là chương trình tạo ra từ mã này có thể làm bất kì gì từ việc thực thi đúng theo ý muốn cho đến việc hư hỏng mỗi lần nó chạy.
Thí dụ: mã sau đây gây ra ứng xử không xác định, vì biến codice_114 được dùng tới nhiều hơn một lần (đồng thời lại có sự biến đổi của chính codice_114 trong lúc tính toán) qua biểu thức codice_220:
Vì không có dãy điểm giữa việc truy cập của codice_114 trong codice_222, nó tạo nên tình trạng là trình dịch có thể tự quyết định tăng codice_114 trước hay sau khi cộng (tùy theo trình dịch và trạng thái máy!) dẫn đến kết quả là 2 hay 3. Mặc dù vậy, vì để cho phép trình dịch thực hiện tốt các quá trình tối ưu, tiêu chuẩn này (của C) còn có thể tạo ra tình hình tệ hơn như trình bày trên. Một cách tổng quát, mọi sự diều chỉnh (hay thay đổi giá trị) và truy cập giữa các dãy điểm có thể gây ra tình huống bất định.