text:
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 qui 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.
- Thí dụ:
// Dòng này sẽ được bỏ qua (không đọc) bởi trình dịch. /* Các dòng này cũng được bỏ qua bởi trình dịch */ ... (Tiếp tục mã C)
Các hàm[sửa | sửa mã nguồn]
Cú pháp[sửa | sửa mã nguồn]
Một hàm C phải bao gồm một kiểu trả về (kiểu đó trả về
void 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à
void 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
return. (Nếu kiểu trả về là
void 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
return 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.)
<kiểu_trả_về> tên_hàm(<danh sách tham số>) { <các_câu_lệnh> return <biến (hay giá trị) có kiểu là kiểu_trả_về>; }
Trong đó,
<danh sách tham số> của
N 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
,:
<kiểu_dữ_liệu> var1, var2,..., varN;
Toàn bộ danh sách này được đặt trong ngoặc đơn ngay sau tên_hàm.
Thí dụ[sửa | sửa mã nguồn]
Hàm
add tính tổng hai số có kiểu integer, hàm
abs 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
1 + 1 = 2 và
absolute value of -2 is 2
#include <stdio.h>; //Chú giải: dòng này khai báo thư viện là stdio.h int add(int x, int y) { return x + y; } int abs(int x) { if (x > 0) return x; if (x < 0) return -x; if (x == 0) return 0; /* đây chỉ là thí dụ cho thấy C có khả năng dùng nhiều hơn 1 câu lệnh return hoàn toàn có thể dùng các câu lệnh khác đơn giản hon. */ } int main(void) { { int z; int y; printf("nhap z:"); scanf("%d",&z); printf("nhap y:"); scanf("%d",&y); printf("%d + %d = %d\n", z, y,add(z, y)); printf ("gia tri tuyet doi cua %d la %d", y, abs(y)); } }
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ả[sửa | sửa mã nguồn]
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
{ và
} 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à
main, đâ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>main 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
main.
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
#include tập tin tiêu đề. Một số hàm thư viện như là
printf đã đượ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
main 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
printf 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[sửa | sửa mã nguồ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)
void incInt(int *y) { (*y)++; // tăng giá trị của x trong main 1 đơn vị } int main(void) { int x = 0; incInt(&x); // chuyển một tham chiếu vào incInt cho 'x' return 0; }
Để 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 điạ chỉ của con trỏ):
void setInt(int **p, int n) { *p = (int *) malloc(sizeof(int)); // đăng kí một vùng nhớ *p = n; // cài giá trị vào } int main(void) { int *p; //khai báo một con trỏ kiểu integer setInt(&p, 42); // chuyển giá trị của 'p' vào. return 0; }
int **p 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ỏ
p.
Hàm scanf làm việc theo cùng một cách thức:
int x; scanf("%d", &x);
Các cấu trúc dòng điều khiển[sửa | sửa mã nguồ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[sửa | sửa mã nguồn]
Câu lệnh phức hợp được bọc trong dấu ngoặc
{ và
} còn được gọi là khối mã. Các câu lệnh phức hợp trong C có dạng.
{ <danh sách khai báo tùy chọn> <đanh sách câu lệnh tùy chọn> }
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[sửa | sửa mã nguồn]
Một câu lệnh (hay một mệnh đề) của C có dạng:
<biểu thức tùy chọn>;
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
; thì biểu thức được gọi là
mệnh đề null (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)[sửa | sửa mã nguồn]
Có 3 loại mệnh đề lựa chọn: hai loại dùng từ khóa
if và một loại dùng từ khóa
switch. Đó là:
Dạng dùng từ khóa
if:[sửa | sửa mã nguồn]
if (<biểu thức>) <mệnh đề1>
if (<biểu thức>) <mệnh đề1> else <mệnh đề2>
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 <mệnh đề1>. Nếu trong câu lệnh
if có thêm từ khóa
else thì <mệnh đề2> sẽ được thực thi một khi <biểu thức> 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 đề
if thì từ khóa
else sẽ được gán vào mệnh đề
if 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
{ và
}.
Dạng dùng từ khóa
switch[sửa | sửa mã nguồn]
Mệnh đề
switch 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
case, sau đó là một biểu thức hằng Hi, và dấu hai chấm
: 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
default, sau đó là dấu hai chấm
: 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 câu lệnh
switchthì không cho phép có hai giá trị hằng bằng nhau. Nghĩa là khi X được đánh giá thì chỉ có tối đa một mệnh đề con được thực thi.
- Các câu lệnh
switchcó thể được dùng trong dạng lồng vào nhau (nest), một từ khóa
casehay
defaultsẽ thuộc vào câu lệnh
switchbên trong nhất (hay nhỏ nhất) chứa nó.
- Một khi dòng điều khiển hoàn tất câu lệnh con Mi thì nó sẽ tiếp tục thi hành các câu lệnh con Mi+1 theo sau cho đến khi nó bị yêu cầu ngưng bởi câu lệnh nhảy (mà thường dược dùng nhiều nhất là câu lệnh
break)
Trong dạng thí dụ dưới đây, nếu <biểu thức X> có giá trị bằng <hằng H2> thì mệnh đề các biểu thức <mệnh đề M2>,<mệnh đề M3>, và <mệnh đề Mdefault> 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
break. Nhưng vì trong mã thí dụ có câu lệnh
break nên dòng điều khiển sẽ ngưng và kết thúc câu lệnh
switch khi thi hành lệnh
break này.
switch (<biểu thức X>) { case <hằng H1>:
<mệnh đề M1>
case <hằng H2>:
<mệnh đề M2>
break;
case <hằng H3>:
<mệnh đề M3>
default:
<mệnh đề Mdefault>
}
Các mệnh đề tái lặp (hay vòng lặp)[sửa | sửa mã nguồn]
C có 3 dạng câu lệnh vòng lặp:
Vòng lặp
do[sửa | sửa mã nguồn]
do <mệnh đề> while (<biểu thức>);
Trong mệnh đề này thì mệnh đề được thực thi lặp lại cho tới khi nào <biểu thức> được đánh giá (hay có giá trị) là
true. Một khi <biểu thức> không còn có giá trị
true nữa thì vòng lặp sẽ bị kết thúc.
Vòng lặp
while[sửa | sửa mã nguồn]
while (<biểu thức>) <mệnh đề>
<mệnh đề> chỉ được thực thi hay thực thi lặp lại khi <biểu thức> có giá trị là
true. Nếu <biểu thức> có giá trị
false thì câu lệnh sẽ bị kết thúc ngay lập tức.
Vòng lặp
for[sửa | sửa mã nguồn]
Dạng C89 của vòng lặp
for là:
for (<biểu thức 1>; <biểu thức 2>; <biểu thức 3>) <câu lệnh>
Nó đã được tổng quát hóa trong C99 thành:
for (<khai báo> <biểu thức 1>; <biểu thức 2>) <câu lệnh>
Khi cả ba biểu thức đều hiện diện trong một câu lệnh
for, 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
for 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.
- Thí dụ: vòng lặp
forsau đây 3 biểu thức ở dạng phức hợp và ngăn cách nhau bởi dấu chấm phẩy
;:
for (x=10,y=1;((x>4) && (y<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>4) && (y<8)) không còn đúng nữa.
Các mệnh đề nhảy (hay bước nhảy)[sửa | sửa mã nguồn]
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à
goto,
continue,
break, và
return.
goto[sửa | sửa mã nguồn]
câu lệnh
goto sẽ có dạng:
goto <nhãn>;
nhãn phải có mặt trong hàm có chứa câu lệnh
goto. Khi đọc đến lệnh này, dòng điều khiển sẽ chuyển đến mệnh đề nhãn.
continue[sửa | sửa mã nguồn]
Mệnh đề
continue 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:; }
break[sửa | sửa mã nguồn]
Mệnh đề
break dùng để kết thúc một câu lệnh vòng lặp hay câu lệnh
switch 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 đó.
return[sửa | sửa mã nguồn]
Một hàm trả dòng điều khiển về nơi gọi nó bằng câu lệnh
return. Khi lệnh
return đượ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[sửa | sửa mã nguồ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[sửa | sửa mã nguồn]
Các kiểu dữ liệu cơ bản[sửa | sửa mã nguồ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ớ.
intđượ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ất1. 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à:
short,
longvà
long long2. Kiểu kí tự mà từ khóa của nó là
char, 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à
float), loại có độ chính xác kép (có đặc tả là
double), và loại có độ chính xác kép mở rộng (có đặc tả là
long double). 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 (
signed) hay không dấu (
unsigned). 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
char,
signed char và
unsigned char đều khác nhau, và kiểu
char có thể là loại có dấu hay không có dấu.
Đối với loại có dấu, thì
bit 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ị.
1 = Trong các kiểu nguyên, độ lớn cao nhất biểu thị giá trị lớn nhất (tùy theo có dấu hay không) mà nó biểu thị. (Xem thêm bản dưới đây)
2 = Từ khóa
long long được đưa thêm vào trong chuẩn C99.
Các hằng số xác định các giá trị biên[sửa | sửa mã nguồn]
Tập tin tiêu đề chuẩn
limits.h 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
float.h sẽ xác định các giá trị nhỏ nhất và lớn nhất của các kiểu
float,
double, và
long double. 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.
1— Định tính
long long chỉ được hỗ trợ trong các trình dịch thỏa mãn chuẩn C99.
2— Các hằng
LLONG_MIN,
LLONG_MAX, và
ULLONG_MAX chỉ được định nghĩa trong
limits.h nếu trình dịch tương ứng thỏa mãn chuẩn C99.
Các giá trị biên điển hình[sửa | sửa mã nguồn]
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.
1— Định tính
long long chỉ được hỗ trợ trong các trình dịch thỏa mãn chuẩn C99.
Kích cỡ và giới hạn của kiểu cơ bản
int (mà không có các định tính
short,
long, hay
long long) 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
size_t — trong tập tin
sys/types.h — 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
int 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[sửa | sửa mã nguồn]
Tiền tố kí tự
* đượ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ả
int biểu thị một kiểu nguyên cơ bản thì đặc tả
int * 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à
ptr:
int *ptr;
Sự tham chiếu[sửa | sửa mã nguồn]
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
ptr sẽ cài cho nó chỉ tới cùng một dữ liệu như là biến nguyên cơ bản
a:
int *ptr; int a; ptr = &a;
Để làm được việc này, toán tử tham chiếu (hay còn gọi là tham chiếu ngược)
& đã đượ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 đuợ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[sửa | sửa mã nguồn]
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
b sẽ được gán đến dữ liệu mà dữ liệu đó được tham chiếu bởi
ptr:
int *ptr; int a, b; a = 10; //gán cho a giá trị là 10 ptr = &a; //phép gán địa chỉ của a (tức là &a) lên con trỏ 'ptr' //để ptr bây giờ chỉ đến địa chỉ có nội dung là 10 b = *ptr //phép gán này cho b một giá trị nằm ở địa chỉ mà 'ptr' //chỉ tới tức là giá trị của b sẽ là 10
Để hoàn tất được thao tác này, toán tử tham chiếu ngược (
&) đã đượ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
*ptr 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[sửa | sửa mã nguồ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
d và biến tham chiếu
ptr được hiểu ngầm.
Các mảng[sửa | sửa mã nguồn]
Khai báo mảng tĩnh[sửa | sửa mã nguồn]
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:
int array[n];
trong đó, tên của mảng là
array sẽ có thể chứa được n giá trị của kiểu cơ bản
int. 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
array 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ử[sửa | sửa mã nguồn]
Các giá trị của một mảng được gọi là các phần tử trong mảng.
- Một cách để truy cập đến các phần tử này là dùng đến cặp kí tự ngoặc vuông dạng
[k]. Trong đó k là chỉ số (hay vị trí thứ tự đếm từ 0). Như vậy, phần tử thứ k trong mảng
arraysẽ có cú pháp
array[k]
Giá trị trả về của
array[k] 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
array đượ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
A có 10 phần tử thì giá trị của phần tử đầu tiên của A là
A[0] và của phần tử cuối dùng là A[9].
- Một cách truy cập khác là dùng con trỏ số học để tham chiếu đến giá trị của các phần tử trong mảng.
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[sửa | sửa mã nguồn]
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ó:
int array[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
calloc 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,
calloc 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ì
calloc 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
int:
int *array; array = calloc(n, sizeof(int));
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
free. 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ị
NULL để 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).
free(array); array = NULL;
Các mảng đa chiều[sửa | sửa mã nguồn]
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:
int array2D[số_hàng][số_cột];
sẽ định nghĩa một mảng hai chiều; chiều thứ nhất có
số_hàng phần tử. Chiều thứ hai sẽ có
số_hàng * số_cột các phần tử—một tập hợp của
số_cột 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,
array2D (nếu
số_hàng là 1) sẽ là một tham chiếu giá trị nguyên mà nó chỉ tới một mảng của
số_cột các phần tử.
Dãy kí tự[sửa | sửa mã nguồn]
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
char. Trong phần này từ "dãy" được để chỉ dãy kí tự.
Các hàm thường dùng là:
strcat(dest, source)- nối một dãy kí tự
sourcetiếp vào vị trí cuối của dãy kí tự
dest
strchr(source, c)- tìm vị trí sự xuất hiện đầu tiên của
ctrong dãy kí tự
sourcevà trả về con trỏ chỉ tới vị trí đó hay con trỏ trống nếu
ckhông tìm thấy trong
source
strcmp(a, b)- so sánh hai dãy kí tự a và b (theo thứ tự từ điển); trả về số âm nếu
anhỏ hơn
b, 0 nếu chúng bằng nhau, dương nếu
alớn hơn
strcpy(dest, source)- chép và thay các kí tự của dãy
sourcevào dãy
dest
strlen(st)- trả về độ dài của
st
strncat(dest, source, n)- nối tối đa
nkí tự từ dãy
sourcetiếp vào vị trí cuối của dãy
dest; các kí tự sau dấu kết thúc
nullsẽ không được chép vào
strncmp(a, b, n)- so sánh từ kí tự đầu cho đến tối đa
nkí tự từ hai dãy
avà
b(theo thứ tự từ điển); hàm trả về số âm nếu phần so sánh của
anhỏ hơn
b, 0 nếu bằng nhau, và dương nếu lớn hơn
strncpy(dest, source, n)- chép từ đầu đến tối đa
nkí tự từ dãy
sourcevào dãy
dest
strrchr(source, c)- tìm vị trí hiện lần cuối cùng của kí tự
ctrong dãy
sourcevà trả về một con trỏ chỉ vào vị trí đó hay con trỏ trống nếu không tìm thấy
ctrong đó
Các hàm ít dùng tới hơn là:
strcoll(s1, s2)- so sánh hai dãy theo một trình tự địa phương đặc thù
strcspn(s1, s2)- trả về chỉ số của kí tự đầu tiên trong
s1trùng với kí tự bất kì nào trong
s2
strerror(err)- trả về một dãy kí tự dưới dạng một thông báo lỗi ứng với mã (câu viết) trong
err
strpbrk(s1, s2)- trả về một con trỏ chỉ vào kí tự đầu tiên nào trong
s1mà trùng với kí tự bất kì trong
s2hay một con trỏ trống nếu không tìm thấy
strspn(s1, s2)- trả về chỉ số của kí tự đầu tiên trong
s1mà nó không xuất hiện trong
s2
strstr(source, subst)- trả về một con trỏ chỉ tới vị trí của dãy
substtrong dãy
sourcehay trả về một con trỏ rỗng nếu không tồn tại một dãy như vậy bên trong
source
strtok(s1, s2)- trả về một con trỏ chỉ đến một
tokenbên trong
s1mà được phân chia ra bởi các kí tự trong
s2
strxfrm(s1, s2, n)- chuyển đổi
s2thành
s1dùng các quy tắc địa phương đặc thù
Tập tin I/O[sửa | sửa mã nguồn]
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
stdio.h.
Tiêu chuẩn I/O[sửa | sửa mã nguồn]
Ba tiêu chuẩn dòng I/O được định nghĩa sẵn là:
stdinđầu vào chuẩn
stdoutđầu ra chuẩn
stderrlỗi chuẩn
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:
#include <stdio.h> int main() { int c; while ((c = getchar()) != EOF) { /* do various things to the characters */ if (anErrorOccurs) { fputs("an error eee occurred\n", stderr); break; } /*... */ putchar(c); /*... */ } return 0; }
Việc chuyển các đối số qua dòng lệnh[sửa | sửa mã nguồn]
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à
argc và biến kia là một mảng con trỏ có tên là
argv, mà mỗi con trỏ chỉ đến một đối số (các đối số được xem như là mảng kí tự)
- Thí dụ mệnh lệnh
myFilt p1 p2 p3
(Lưu ý: không có gì bảo đảm rằng các dãy kí tự riêng lẻ là liền nhau)
Đố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
argv[1],
argv[2], và
argv[3] như là được chỉ ra trong chương trình sau:
#include <stdio.h> int main(int argc, char *argv[]) { int i; printf ("argc\t= %i\n", argc); for (i = 0; i < argc; i++) printf ("argv[%i]\t= %s\n", i, argv[i]); return 0; }
Thứ tự đánh giá[sửa | sửa mã nguồn]
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:
- Các kết thúc của mệnh đề tại các dấu chấm phẩy.
- Toán tử dãy: dấu phẩy.
- Các toán tử ngắn mạch: gồm phép và (
&&) và phép hoặc (
||).
- Toán tử điều kiện (
A?B:C): Giá trị của biểu thức A được đánh giá trước. Nếu A là đúng thì B sẽ được đánh giá bỏ qua biểu thức C. Nếu A sai thì B bị bỏ qua và chỉ có C được đánh giá tiếp.
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
(a() || b()), nếu
a() trả về giá trị đúng thì trình dịch sẽ không cần đánh giá
b() nữa (vì lúc đó đã đủ để kết luận mệnh đề
(a() || b()) 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[sửa | sửa mã nguồn]
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
b đượ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
b trong lúc tính toán) qua biểu thức
a = b + b++;:
#include <stdio.h> int main (void) { int a, b = 1; a = b + b++; printf ("%d\n", a); return 0; }
Vì không có dãy điểm giữa việc truy cập của
b trong
b + b++, nó tạo nên tình trạng là trình dịch có thể tự quyết định tăng
b 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ó 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.
Xem thêm[sửa | sửa mã nguồn]
Tham khảo[sửa | sửa mã nguồn]
- Kernighan, Brian W. and Dennis M. Ritchie. The C Programming Language.

markdown:
# Cú pháp ngôn ngữ C
|
|![]()
|
|Bài viết hoặc đoạn này cần thêm
Những nội dung không có nguồn có thể bị
**Cú pháp ngôn ngữ (lập trình) C** là tập hợp các qui 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](/wiki/C_(ng%C3%B4n_ng%E1%BB%AF_l%E1%BA%ADp_tr%C3%ACnh)).
- Thí dụ:
// Dòng này sẽ được bỏ qua (không đọc) bởi trình dịch. /* Các dòng này cũng được bỏ qua bởi trình dịch */ ... (Tiếp tục mã C)
## Các hàm[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=1) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=1)]
### Cú pháp[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=2) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=2)]
Một hàm C phải bao gồm một
[kiểu trả về](/w/index.php?title=Ki%E1%BB%83u_tr%E1%BA%A3_v%E1%BB%81&action=edit&redlink=1) (kiểu đó trả về
void 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à
void 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
return. (Nếu kiểu trả về là
void 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
return 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.)
<kiểu_trả_về> tên_hàm(<danh sách tham số>) { <các_câu_lệnh> return <biến (hay giá trị) có kiểu là kiểu_trả_về>; }
Trong đó,
<danh sách tham số> của
N 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
,:
<kiểu_dữ_liệu> var1, var2,..., varN;
Toàn bộ danh sách này được đặt trong ngoặc đơn ngay sau tên_hàm.
#### Thí dụ[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=3) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=3)]
Hàm
add tính tổng hai số có kiểu
[integer](/w/index.php?title=Integer&action=edit&redlink=1), hàm
abs 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
1 + 1 = 2 và
absolute value of -2 is 2
#include <stdio.h>; //Chú giải: dòng này khai báo thư viện là stdio.h int add(int x, int y) { return x + y; } int abs(int x) { if (x > 0) return x; if (x < 0) return -x; if (x == 0) return 0; /* đây chỉ là thí dụ cho thấy C có khả năng dùng nhiều hơn 1 câu lệnh return hoàn toàn có thể dùng các câu lệnh khác đơn giản hon. */ } int main(void) { { int z; int y; printf("nhap z:"); scanf("%d",&z); printf("nhap y:"); scanf("%d",&y); printf("%d + %d = %d\n", z, y,add(z, y)); printf ("gia tri tuyet doi cua %d la %d", y, abs(y)); } }
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ả[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=4) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=4)]
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](/wiki/C_(ng%C3%B4n_ng%E1%BB%AF_l%E1%BA%ADp_tr%C3%ACnh)#INCLUDE).
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](/wiki/Fortran) hay các thủ tục của [Pascal](/wiki/Pascal_(ng%C3%B4n_ng%E1%BB%AF_l%E1%BA%ADp_tr%C3%ACnh)). Đị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
{ và
} 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à
, đâ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.
[main](/w/index.php?title=H%C3%A0m_main_(l%E1%BA%ADp_tr%C3%ACnh)&action=edit&redlink=1)
int main (void) { return 0; }
Hàm code>main 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](/wiki/H%E1%BB%87_%C4%91i%E1%BB%81u_h%C3%A0nh) hay các nơi khác (như là phát triển các [bộ điều vận](/w/index.php?title=B%E1%BB%99_%C4%91i%E1%BB%81u_v%E1%BA%ADn&action=edit&redlink=1), các [phần sụn](/wiki/Firmware), 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
main.
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ề](/w/index.php?title=T%E1%BA%ADp_tin_ti%C3%AAu_d%E1%BB%81&action=edit&redlink=1) trong câu lệnh dạng
#include tập tin tiêu đề. Một số hàm thư viện như là
đã được định nghĩa bởi chuẩn C, chúng được tham chiếu như là các hàm
[printf](/w/index.php?title=Printf&action=edit&redlink=1) [thư viện chuẩn](/w/index.php?title=Th%C6%B0_vi%E1%BB%87n_chu%E1%BA%A9n_ANSI_C&action=edit&redlink=1).
Một hàm có thể trả về một giá trị cho môi trường gọi nó. Khi hàm
main 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
printf 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[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=5) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=5)]
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](#REF_TYPE))
void incInt(int *y) { (*y)++; // tăng giá trị của x trong main 1 đơn vị } int main(void) { int x = 0; incInt(&x); // chuyển một tham chiếu vào incInt cho 'x' return 0; }
Để 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 điạ chỉ của con trỏ):
void setInt(int **p, int n) { *p = (int *) malloc(sizeof(int)); // đăng kí một vùng nhớ *p = n; // cài giá trị vào } int main(void) { int *p; //khai báo một con trỏ kiểu integer setInt(&p, 42); // chuyển giá trị của 'p' vào. return 0; }
int **p 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ỏ
p.
Hàm
[scanf](/w/index.php?title=Scanf&action=edit&redlink=1) làm việc theo cùng một cách thức:
int x; scanf("%d", &x);
## Các cấu trúc dòng điều khiển[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=6) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=6)]
Một cách cơ bản thì C là
[ngôn ngữ dạng tự do](/w/index.php?title=Ng%C3%B4n_ng%E1%BB%AF_d%E1%BA%A1ng_t%E1%BB%B1_do&action=edit&redlink=1). 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](/wiki/C%C3%A2u_l%E1%BB%87nh)".
### Các mệnh đề phức hợp[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=7) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=7)]
Câu lệnh phức hợp được bọc trong dấu ngoặc
{ và
} còn được gọi là
**khối mã**. Các câu lệnh phức hợp trong C có dạng.
{ <danh sách khai báo tùy chọn> <đanh sách câu lệnh tùy chọn> }
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[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=8) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=8)]
Một câu lệnh (hay một mệnh đề) của C có dạng:
<biểu thức tùy chọn>;
là một
[mệnh đề biểu thức](/w/index.php?title=M%E1%BB%87nh_%C4%91%E1%BB%81_bi%E1%BB%83u_th%E1%BB%A9c&action=edit&redlink=1). Nếu biểu thức này không có nội dung (mà chỉ còn lại dấu
; thì biểu thức được gọi là
(hay mệnh dề rỗng). (Theo ngôn ngữ máy
**mệnh đề null** [Assembler](/w/index.php?title=Assembler&action=edit&redlink=1) 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)[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=9) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=9)]
Có 3 loại
[mệnh đề lựa chọn](/w/index.php?title=M%E1%BB%87nh_%C4%91%E1%BB%81_l%E1%BB%B1a_ch%E1%BB%8Dn&action=edit&redlink=1): hai loại dùng từ khóa
if và một loại dùng từ khóa
switch. Đó là:
#### Dạng dùng từ khóa
if:[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=10) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=10)]
if (<biểu thức>) <mệnh đề1>
if (<biểu thức>) <mệnh đề1> else <mệnh đề2>
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 <mệnh đề1>. Nếu trong câu lệnh
if có thêm từ khóa
else thì <mệnh đề2> sẽ được thực thi một khi <biểu thức> 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 đề
if thì từ khóa
else sẽ được gán vào mệnh đề
if 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
{ và
}.
#### Dạng dùng từ khóa
switch[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=11) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=11)]
Mệnh đề
switch 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](/w/index.php?title=Bi%E1%BB%83u_th%E1%BB%A9c&action=edit&redlink=1) **X** (biểu thức này phải có [kiểu nguyên](/w/index.php?title=Ki%E1%BB%83u_nguy%C3%AAn&action=edit&redlink=1)). 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
case, sau đó là một biểu thức hằng
**H i**, và dấu hai chấm
:gắn liền tiếp theo đó là mệnh đề con
**M**. i
Khi giá trị của
**X** trùng với một giá trị **H i** được nêu ở đâu thì mệnh đề con đi gắn liền vói hằng tại đó (tức là **M**) sẽ được thực thi. i
Nếu
**X** không bằng với bất kì giá trị **H i** nào thì người lập trình có thể dùng thêm từ khóa
default, sau đó là dấu hai chấm
:và tiếp theo là một mệnh đề con
**M**. Mệnh đề con này sẽ được thực thi khi mà giá trị của default **X**khác với mọi giá trị hằng **H**. i
Lưu ý:
- Trong câu lệnh
switchthì không cho phép có hai giá trị hằng bằng nhau. Nghĩa là khi
**X**được đánh giá thì chỉ có tối đa một mệnh đề con được thực thi.
- Các câu lệnh
switchcó thể được dùng trong dạng lồng vào nhau (
*nest*), một từ khóa
casehay
defaultsẽ thuộc vào câu lệnh
switchbên trong nhất (hay nhỏ nhất) chứa nó.
- Một khi dòng điều khiển hoàn tất câu lệnh con
**M**thì nó sẽ tiếp tục thi hành các câu lệnh con i **M**theo sau cho đến khi nó bị yêu cầu ngưng bởi câu lệnh nhảy (mà thường dược dùng nhiều nhất là câu lệnh i+1
break)
Trong dạng thí dụ dưới đây, nếu <biểu thức X> có giá trị bằng <hằng H
2> thì mệnh đề các biểu thức <mệnh đề M 2>,<mệnh đề M 3>, và <mệnh đề M default> 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
break. Nhưng vì trong mã thí dụ có câu lệnh
break nên dòng điều khiển sẽ ngưng và kết thúc câu lệnh
switch khi thi hành lệnh
break này.
switch (<biểu thức X>) { case <hằng H
1>:
<mệnh đề M
1>
case <hằng H
2>:
<mệnh đề M
2>
break;
case <hằng H
3>:
<mệnh đề M
3>
default:
<mệnh đề M
default>
}
### Các mệnh đề tái lặp (hay vòng lặp)[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=12) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=12)]
C có 3 dạng
[câu lệnh vòng lặp](/w/index.php?title=C%C3%A2u_l%E1%BB%87nh_v%C3%B2ng_l%E1%BA%B7p&action=edit&redlink=1):
#### Vòng lặp
do[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=13) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=13)]
do <mệnh đề> while (<biểu thức>);
Trong mệnh đề này thì mệnh đề được thực thi lặp lại cho tới khi nào <biểu thức> được đánh giá (hay có giá trị) là
true. Một khi <biểu thức> không còn có giá trị
true nữa thì vòng lặp sẽ bị kết thúc.
#### Vòng lặp
while[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=14) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=14)]
while (<biểu thức>) <mệnh đề>
<mệnh đề> chỉ được thực thi hay thực thi lặp lại khi <biểu thức> có giá trị là
true. Nếu <biểu thức> có giá trị
false thì câu lệnh sẽ bị kết thúc ngay lập tức.
#### Vòng lặp
for[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=15) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=15)]
Dạng C89 của vòng lặp
for là:
for (<biểu thức 1>; <biểu thức 2>; <biểu thức 3>) <câu lệnh>
Nó đã được tổng quát hóa trong C99 thành:
for (<khai báo> <biểu thức 1>; <biểu thức 2>) <câu lệnh>
Khi cả ba biểu thức đều hiện diện trong một câu lệnh
for, 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
for 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.
- Thí dụ: vòng lặp
forsau đây 3 biểu thức ở dạng phức hợp và ngăn cách nhau bởi dấu chấm phẩy
;:
for (x=10,y=1;((x>4) && (y<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>4) && (y<8)) không còn đúng nữa.
### Các mệnh đề nhảy (hay bước nhảy)[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=16) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=16)]
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](/w/index.php?title=M%E1%BB%87nh_%C4%91%E1%BB%81_nh%E1%BA%A3y&action=edit&redlink=1) trong C là
goto,
continue,
break, và
return.
goto[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=17) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=17)]
câu lệnh
goto sẽ có dạng:
goto <nhãn>;
[nhãn](/w/index.php?title=Nh%C3%A3n_(ng%C3%B4n_ng%E1%BB%AF_l%E1%BA%ADp_tr%C3%ACnh)&action=edit&redlink=1) phải có mặt trong hàm có chứa câu lệnh
goto. Khi đọc đến lệnh này, dòng điều khiển sẽ chuyển đến mệnh đề nhãn.
continue[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=18) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=18)]
Mệnh đề
continue 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:; }
break[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=19) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=19)]
Mệnh đề
break dùng để kết thúc một câu lệnh vòng lặp hay câu lệnh
switch 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 đó.
return[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=20) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=20)]
Một hàm trả dòng điều khiển về nơi gọi nó bằng câu lệnh
return. Khi lệnh
return đượ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[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=21) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=21)] *Xem thêm bài chính* [Phép toán trong C và C++](/w/index.php?title=Ph%C3%A9p_to%C3%A1n_trong_C_v%C3%A0_C%2B%2B&action=edit&redlink=1)
Để tham khảo, sau đây là bảng thứ tự ưu tiên của các phép toán theo
[C89](/w/index.php?title=C89&action=edit&redlink=1):
|Phép toán||Mô tả||Hướng tiến hành|
|
||ngoặc đơn (nhóm)
|
phần chỉ số của mảng
|từ trái sang phải|
|
||tiền tố tăng/giảm
|
dấu dương/âm
|từ phải sang trái|
|
||nhân/chia/mô dun||từ trái sang phải|
|
||cộng/trừ|
|
||phép toán bit <ocde>left shift/right shift|
|
||quan hệ nhỏ hơn/nhỏ hơn hay bằng
|
quan hệ lớn hơn/lớn hơn hay bằng
|
||bằng với/khác với|
|
||phép toán bit
|
|
||phép toán bít
|
|
||phép toán bit
|
|
||phép toán bool
|
|
||phép toán bool
|
|
||điều kiện tam phân||từ phải sang trái|
|
||phép gán giá trị trực tiếp
|
phép gán giá trị cộng thêm/trừ bớt
|
||toán tử
||từ trái sang phải|
Nguồn:
[C Operator Precedence and Associativity](http://www.difranco.net/cop2220/op-prec.htm)
## Khai báo dữ liệu[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=22) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=22)]
### Các kiểu dữ liệu cơ bản[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=23) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=23)]
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ớ.
intđượ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
1. 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à:
short,
longvà
long long
2. Kiểu kí tự mà từ khóa của nó là
char, 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](/wiki/Ki%E1%BA%BFn_tr%C3%BAc_m%C3%A1y_t%C3%ADnh)) 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à
float), loại có độ chính xác kép (có đặc tả là
double), và loại có độ chính xác kép mở rộng (có đặc tả là
long double). 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 (
signed) hay không dấu (
unsigned). 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
char,
signed char và
unsigned char đều khác nhau, và kiểu
char có thể là loại có dấu hay không có dấu.
Đối với loại có dấu, thì
bit 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ị.
1 = Trong các kiểu nguyên, độ lớn cao nhất biểu thị giá trị lớn nhất (tùy theo có dấu hay không) mà nó biểu thị. (Xem thêm [bản dưới đây](#C.C3.A1c_h.E1.BA.B1ng_s.E1.BB.91_.C4.91.E1.BB.83_x.C3.A1c_.C4.91.E1.BB.8Bnh_c.C3.A1c_gi.C3.A1_tr.E1.BB.8B_bi.C3.AAn_c.E1.BB.A7a_c.C3.A1c_ki.E1.BB.83u_c.C6.A1_b.E1.BA.A3n)) 2 = Từ khóa
long long được đưa thêm vào trong chuẩn C99.
#### Các hằng số xác định các giá trị biên[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=24) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=24)]
Tập tin tiêu đề chuẩn
limits.h 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
float.h sẽ xác định các giá trị nhỏ nhất và lớn nhất của các kiểu
float,
double, và
long double. 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](/w/index.php?title=IEEE_754&action=edit&redlink=1).
|
|Đặc tả hiểu ngầm |
|Đặc tả viết rõ ra |
|Giá trị nhỏ nhất |
|Giá trị lớn nhất
|
||
|viết y hệt |
||
|
|
||
|viết y hệt |
||
|
|
||
|viết y hệt |0||
|
|
||
||
||
|
|
||
||0||
|
|
|không viết gì hết, |
||
||
|
|
||
||0||
|
|
||
||
||
|
|
||
||0||
|
|
|1 |
|1 |
|2 |
|2
|
|1 |
|1 |0||
|2 1— Định tính
long long chỉ được hỗ trợ trong các trình dịch thỏa mãn chuẩn C99.
2— Các hằng
LLONG_MIN,
LLONG_MAX, và
ULLONG_MAX chỉ được định nghĩa trong
limits.h nếu trình dịch tương ứng thỏa mãn chuẩn C99.
#### Các giá trị biên điển hình[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=25) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=25)]
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](/w/index.php?title=ISO_C&action=edit&redlink=1) cung cấp tiêu đề [inttypes.h](/w/index.php?title=Inttypes.h&action=edit&redlink=1), 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.
|Đặc tả hiểu ngầm||Đặc tả viết rõ ra||Số bit||Số byte||Giá trị nhỏ nhất||Giá trị lớn nhất|
|
||
|viết y hệt |8||1||-128 or 0||127 hay 255|
|
||
|viết y hệt |8||1||-128||127|
|
||
|viết y hệt |8||1||0||255|
|
||
||16||2||-32 768||32 767|
|
||
||16||2||0||65 535|
|
||
||32||4||-2 147 483 648||2 147 483 647|
|
||
||32||4||0||4 294 967 295|
|
|1 |
|1 |64||8||-9 223 372 036 854 775 808||9 223 372 036 854 775 807|
|
|1 |
|1 |64||8||0||18 446 744 073 709 551 615|1— Định tính
long long chỉ được hỗ trợ trong các trình dịch thỏa mãn chuẩn C99.
Kích cỡ và giới hạn của kiểu cơ bản
int (mà không có các định tính
short,
long, hay
long long) 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
size_t — trong tập tin
sys/types.h — 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](/w/index.php?title=%C4%90%E1%BA%B7c_t%E1%BA%A3_UNIX_%C4%91%C6%A1n&action=edit&redlink=1) chỉ ra rằng kiểu
int phải có ít nhất 32 bit, mặc dù chuẩn
[ISO C](/w/index.php?title=ISO_C&action=edit&redlink=1) chỉ yêu cầu có 16 bit.
### Các kiểu tham chiếu[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=26) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=26)]
Tiền tố kí tự
* đượ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ả
int biểu thị một kiểu nguyên cơ bản thì đặc tả
int * 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](/wiki/C%C3%A2u_l%E1%BB%87nh) sau đây khai báo một biến tham chiếu nguyên có tên là
ptr:
int *ptr;
#### Sự tham chiếu[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=27) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=27)]
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
ptr sẽ cài cho nó chỉ tới cùng một dữ liệu như là biến nguyên cơ bản
a:
int *ptr; int a; ptr = &a;
Để làm được việc này, toán tử tham chiếu (hay còn gọi là
*tham chiếu ngược*)
& đã đượ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 đuợ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[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=28) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=28)]
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
b sẽ được gán đến dữ liệu mà dữ liệu đó được tham chiếu bởi
ptr:
int *ptr; int a, b; a = 10; //gán cho a giá trị là 10 ptr = &a; //phép gán địa chỉ của a (tức là &a) lên con trỏ 'ptr' //để ptr bây giờ chỉ đến địa chỉ có nội dung là 10 b = *ptr //phép gán này cho b một giá trị nằm ở địa chỉ mà 'ptr' //chỉ tới tức là giá trị của b sẽ là 10
Để hoàn tất được thao tác này, toán tử tham chiếu ngược (
&) đã đượ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
*ptr 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[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=29) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=29)]
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
d và biến tham chiếu
ptr được hiểu ngầm.
|Đến một giá trị cơ bản||Đến một giá trị tham chiếu|
|Từ một giá trị cơ bản||
||
|
|Từ một giá trị tham chiếu||
||
|
### Các mảng[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=30) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=30)]
#### Khai báo mảng tĩnh[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=31) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=31)]
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:
int array[n];
trong đó, tên của mảng là
array sẽ có thể chứa được n giá trị của kiểu cơ bản
int. 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
array 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ử[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=32) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=32)]
Các giá trị của một mảng được gọi là các
**phần tử** trong mảng.
- Một cách để truy cập đến các phần tử này là dùng đến cặp kí tự ngoặc vuông dạng
[k]. Trong đó k là
**chỉ số**(hay vị trí thứ tự đếm từ 0). Như vậy, phần tử thứ k trong mảng
arraysẽ có cú pháp
array[k]
Giá trị trả về của
array[k] 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
array đượ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
A có 10 phần tử thì giá trị của phần tử đầu tiên của A là
A[0] và của phần tử cuối dùng là A[9].
- Một cách truy cập khác là dùng
[con trỏ số học](/w/index.php?title=Con_tr%E1%BB%8F_s%E1%BB%91_h%E1%BB%8Dc&action=edit&redlink=1)để tham chiếu đến giá trị của các phần tử trong mảng.
Bảng sau đây sẽ minh họa cách dùng của cả hai phương pháp:
|Phần tử vị trí||0||1||2||n|
|Kiểu dùng cơ bản||
||
||
||
|
|Dùng con trỏ||
||
||
||
|
#### Các mảng động[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=33) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=33)]
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ó:
int array[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](/wiki/Th%C6%B0_vi%E1%BB%87n_chu%E1%BA%A9n_C). Hàm
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,
[calloc](/w/index.php?title=Calloc&action=edit&redlink=1)
calloc 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ì
calloc trả về
[con trỏ rỗng](/w/index.php?title=Con_tr%E1%BB%8F_r%E1%BB%97ng&action=edit&redlink=1). 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
int:
int *array; array = calloc(n, sizeof(int));
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](/wiki/H%E1%BB%87_%C4%91i%E1%BB%81u_h%C3%A0nh). Thao tác này có thể tiến hành bằng hàm
free. 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ị
NULL để 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).
free(array); array = NULL;
#### Các mảng đa chiều[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=34) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=34)]
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:
int array2D[số_hàng][số_cột];
sẽ định nghĩa một mảng hai chiều; chiều thứ nhất có
số_hàng phần tử. Chiều thứ hai sẽ có
số_hàng * số_cột các phần tử—một tập hợp của
số_cột 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,
array2D (nếu
số_hàng là 1) sẽ là một tham chiếu giá trị nguyên mà nó chỉ tới một mảng của
số_cột các phần tử.
## Dãy kí tự[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=35) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=35)]
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](/w/index.php?title=Th%C6%B0_vi%E1%BB%87n_chu%E1%BA%A9n&action=edit&redlink=1). 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
char. Trong phần này từ "dãy" được để chỉ dãy kí tự.
Các hàm thường dùng là:
strcat(dest, source)- nối một dãy kí tự
sourcetiếp vào vị trí cuối của dãy kí tự
dest
strchr(source, c)- tìm vị trí sự xuất hiện đầu tiên của
ctrong dãy kí tự
sourcevà trả về con trỏ chỉ tới vị trí đó hay con trỏ trống nếu
ckhông tìm thấy trong
source
strcmp(a, b)- so sánh hai dãy kí tự a và b (theo thứ tự từ điển); trả về số âm nếu
anhỏ hơn
b, 0 nếu chúng bằng nhau, dương nếu
alớn hơn
strcpy(dest, source)- chép và thay các kí tự của dãy
sourcevào dãy
dest
strlen(st)- trả về độ dài của
st
strncat(dest, source, n)- nối tối đa
nkí tự từ dãy
sourcetiếp vào vị trí cuối của dãy
dest; các kí tự sau dấu kết thúc
nullsẽ không được chép vào
strncmp(a, b, n)- so sánh từ kí tự đầu cho đến tối đa
nkí tự từ hai dãy
avà
b(theo thứ tự từ điển); hàm trả về số âm nếu phần so sánh của
anhỏ hơn
b, 0 nếu bằng nhau, và dương nếu lớn hơn
strncpy(dest, source, n)- chép từ đầu đến tối đa
nkí tự từ dãy
sourcevào dãy
dest
strrchr(source, c)- tìm vị trí hiện lần cuối cùng của kí tự
ctrong dãy
sourcevà trả về một con trỏ chỉ vào vị trí đó hay con trỏ trống nếu không tìm thấy
ctrong đó
Các hàm ít dùng tới hơn là:
strcoll(s1, s2)- so sánh hai dãy theo một trình tự địa phương đặc thù
strcspn(s1, s2)- trả về chỉ số của kí tự đầu tiên trong
s1trùng với kí tự bất kì nào trong
s2
strerror(err)- trả về một dãy kí tự dưới dạng một thông báo lỗi ứng với mã (câu viết) trong
err
strpbrk(s1, s2)- trả về một con trỏ chỉ vào kí tự đầu tiên nào trong
s1mà trùng với kí tự bất kì trong
s2hay một con trỏ trống nếu không tìm thấy
strspn(s1, s2)- trả về chỉ số của kí tự đầu tiên trong
s1mà nó không xuất hiện trong
s2
strstr(source, subst)- trả về một con trỏ chỉ tới vị trí của dãy
substtrong dãy
sourcehay trả về một con trỏ rỗng nếu không tồn tại một dãy như vậy bên trong
source
strtok(s1, s2)- trả về một con trỏ chỉ đến một
tokenbên trong
s1mà được phân chia ra bởi các kí tự trong
s2
strxfrm(s1, s2, n)- chuyển đổi
s2thành
s1dùng các quy tắc địa phương đặc thù
## Tập tin I/O[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=36) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=36)]
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
stdio.h.
### Tiêu chuẩn I/O[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=37) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=37)]
Ba tiêu chuẩn
[dòng I/O](/w/index.php?title=D%C3%B2ng_I/O&action=edit&redlink=1) được định nghĩa sẵn là:
stdin
[đầu vào chuẩn](/w/index.php?title=%C4%90%E1%BA%A7u_v%C3%A0o_chu%E1%BA%A9n&action=edit&redlink=1)
stdout
[đầu ra chuẩn](/w/index.php?title=%C4%90%E1%BA%A7u_ra_chu%E1%BA%A9n&action=edit&redlink=1)
stderr
[lỗi chuẩn](/w/index.php?title=C%C3%A1c_d%C3%B2ng_chu%E1%BA%A9n&action=edit&redlink=1)
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](/w/index.php?title=M%C3%B4i_tr%C6%B0%E1%BB%9Dng_c%E1%BB%A7a_th%E1%BB%9Di_gian_thi_h%C3%A0nh&action=edit&redlink=1), 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](/w/index.php?title=Ch%C6%B0%C6%A1ng_tr%C3%ACnh_b%E1%BB%99_l%E1%BB%8Dc&action=edit&redlink=1) được cấu trúc một cách điển hình:
#include <stdio.h> int main() { int c; while ((c = getchar()) != EOF) { /* do various things to the characters */ if (anErrorOccurs) { fputs("an error eee occurred\n", stderr); break; } /*... */ putchar(c); /*... */ } return 0; }
## Việc chuyển các đối số qua dòng lệnh[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=38) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=38)]
Các
[tham số](/wiki/Tham_s%E1%BB%91) được gõ vào một [dòng lệnh](/w/index.php?title=D%C3%B2ng_l%E1%BB%87nh&action=edit&redlink=1) 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à
argc và biến kia là một
[mảng con trỏ](/w/index.php?title=M%E1%BA%A3ng_con_tr%E1%BB%8F&action=edit&redlink=1) có tên là
argv, mà mỗi con trỏ chỉ đến một đối số (các đối số được xem như là
[mảng kí tự](/w/index.php?title=M%E1%BA%A3ng_k%C3%AD_t%E1%BB%B1&action=edit&redlink=1))
- Thí dụ mệnh lệnh
myFilt p1 p2 p3
(Lưu ý: không có gì bảo đảm rằng các dãy kí tự riêng lẻ là liền nhau)
Đố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
argv[1],
argv[2], và
argv[3] như là được chỉ ra trong chương trình sau:
#include <stdio.h> int main(int argc, char *argv[]) { int i; printf ("argc\t= %i\n", argc); for (i = 0; i < argc; i++) printf ("argv[%i]\t= %s\n", i, argv[i]); return 0; }
## Thứ tự đánh giá[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=39) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=39)]
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: *Các kết thúc của mệnh đề*tại các dấu chấm phẩy. *Toán tử dãy*: dấu phẩy. *Các toán tử ngắn mạch*: gồm phép *và*(
&&) và phép
*hoặc*(
||).
*Toán tử điều kiện*(
A?B:C): Giá trị của biểu thức A được đánh giá trước. Nếu A là đúng thì B sẽ được đánh giá bỏ qua biểu thức C. Nếu A sai thì B bị bỏ qua và chỉ có C được đánh giá tiếp.
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
(a() || b()), nếu
a() trả về giá trị đúng thì trình dịch sẽ không cần đánh giá
b() nữa (vì lúc đó đã đủ để kết luận mệnh đề
(a() || b()) 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[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=40) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=40)]
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
b đượ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
b trong lúc tính toán) qua biểu thức
a = b + b++;:
#include <stdio.h> int main (void) { int a, b = 1; a = b + b++; printf ("%d\n", a); return 0; }
Vì không có dãy điểm giữa việc truy cập của
b trong
b + b++, nó tạo nên tình trạng là trình dịch có thể tự quyết định tăng
b 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ó 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.
## Xem thêm[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=41) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=41)]
## Tham khảo[
[sửa](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&veaction=edit&vesection=42) | [sửa mã nguồn](/w/index.php?title=C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C&action=edit§ion=42)]
- Kernighan, Brian W. and
[Dennis M. Ritchie](/wiki/Dennis_Ritchie). *.* [The C Programming Language](/w/index.php?title=The_C_Programming_Language_(book)&action=edit&redlink=1)

X-Cache: cp1067 miss (0), cp1065 frontend miss (0)


text:
Danh sách các tiểu bang Hoa Kỳ theo GDP (danh nghĩa)
Bách khoa toàn thư mở Wikipedia
Bước tới:
menu
,
tìm kiếm
Bản đồ thể hiện tổng sản phẩm GDP theo từng bang (2005)
Danh sách các bang và lãnh thổ của Hoa Kỳ theo GDP năm 2012
[1]
GDP
Hạng
Bang
lãnh thổ
GDP
(triệu
Đô la Mỹ
)
Tỷ lệ so với
GDP quốc gia
Dân số
(triệu)
GDP
trên người ($)
Hạng GDP
trên người
Hoa Kỳ
16.202.700
100,00
316,8
47.482
1
California
2.080.600
13,34
37,3
51.914
13
2
Texas
1.458.300
8,92
25,1
58.099
7
3
New York
1.156.500
7,68
19,4
57.423
8
4
Florida
754.000
5,20
18,8
40.106
40
5
Illinois
644.200
4,44
12,8
50.328
16
6
Pennsylvania
575.600
3,97
12,7
45.323
25
7
New Jersey
497.000
3,42
8,8
56.477
9
8
Ohio
483.400
3,33
11,5
42.035
33
9
Virginia
427.700
2,95
8,0
53.463
10
10
Bắc Carolina
407.400
2,81
9,5
42.884
31
11
Georgia
403.100
2,79
9,7
41.711
35
12
Massachusetts
377.700
2,60
6,5
58.108
6
13
Michigan
372.400
2,57
9,9
37.616
42
14
Washington
351.100
2,42
6,7
52.403
11
15
Maryland
300.000
2,07
5,8
51.724
14
16
Indiana
267.600
1,84
6,5
41.169
36
17
Minnesota
267.100
1,84
5,3
50.396
15
18
Arizona
261.300
1,80
6,4
40.828
39
19
Colorado
259.700
1,79
5,0
51.940
12
20
Wisconsin
251.400
1,73
5,7
44.105
29
21
Tennessee
250.300
1,72
6,3
39.730
41
22
Missouri
246.700
1,70
6,0
41.117
37
23
Connecticut
233.400
1,61
3,6
64.833
4
24
Louisiana
213.600
1,47
4,5
47.467
22
25
Alabama
174.400
1,20
4,8
36.333
46
26
Oregon
168.900
1,16
3,8
44.447
27
27
Nam Carolina
164.300
1,13
4,6
35.717
48
28
Kentucky
161.400
1,11
4,3
37.535
43
29
Oklahoma
160.500
1,11
3,8
42.237
32
30
Iowa
147.200
1,01
3,0
49.067
20
31
Kansas
128.500
0,89
2,9
44.310
28
32
Nevada
127.500
0,88
2,7
47.222
24
33
Utah
116.900
0,81
2,8
41.750
34
34
Arkansas
105.800
0,73
2,9
36.483
45
35
Washington, D.C.
104.700
0,72
0,6
174.500
1
36
Mississippi
98.900
0,68
3,0
32.967
51
37
Nebraska
89.600
0,62
1,8
49.778
18
38
New Mexico
75.500
0,52
2,1
35.952
47
39
Hawaii
68.900
0,47
1,4
49.214
19
40
Tây Virginia
66.600
0,46
1,9
35.053
49
41
Delaware
62.700
0,43
0,9
69.667
2
42
New Hampshire
61.600
0,42
1,3
47.385
23
43
Idaho
54.800
0,38
1,6
34.250
50
44
Maine
53.200
0,37
1,3
40.923
38
45
Rhode Island
49.500
0,34
1,1
45.000
26
46
Alaska
45.600
0,31
0,7
65.143
3
47
Nam Dakota
39.900
0,27
0,8
49.875
17
48
Wyoming
38.200
0,26
0,6
63.667
5
49
Montana
37.200
0,26
1,0
37.200
44
50
Bắc Dakota
33.400
0,23
0,7
47.714
21
51
Vermont
26.400
0,18
0,6
44.000
30
2006
Xếp hạng
Tiểu bang
Tổng sản phẩm 2006
(triệu
$
)
2005
Xếp hạng
Tổng sản phẩm 2005
(triệu
$
)
2004
Xếp hạng
Tổng sản phẩm2004
(triệu
$
)
1
California
1.727.355
1
1.616.351
1
1.515.453
2
Texas
1.065.891
2
989.333
3
904.412
3
New York
1.021.944
3
961.385
2
908.308
4
Florida
713.505
4
666.639
4
607.201
5
Illinois
589.598
5
555.599
5
534.364
6
Pennsylvania
510.293
6
486.139
6
464.467
7
Ohio
461.302
7
442.243
7
424.562
8
New Jersey
434.177
8
427.654
8
409.156
9
Michigan
381.003
9
372.148
9
363.386
10
Georgia
379.550
10
358.365
10
337.622
11
Bắc Carolina
374.525
11
350.700
12
324.622
12
Virginia
369.260
12
350.692
11
325.467
13
Massachusetts
337.570
13
320.050
13
309.483
14
Washington
293.531
14
271.381
14
252.384
15
Maryland
257.815
15
244.447
16
229.158
16
Indiana
248.915
16
236.357
15
229.618
17
Minnesota
244.546
17
231.437
17
222.628
18
Tennessee
238.029
18
224.995
18
214.400
19
Arizona
232.463
22
212.312
22
194.134
20
Colorado
230.478
21
214.337
21
198.407
21
Wisconsin
227.230
19
216.985
19
208.269
22
Missouri
225.876
20
215.073
20
204.733
23
Connecticut
204.134
23
193.496
23
183.873
24
Louisiana
193.138
24
180.336
24
162.646
25
Alabama
160.569
25
151.342
25
141.702
26
Oregon
151.301
26
141.831
26
135.014
27
Nam Carolina
149.214
27
140.088
27
132.348
28
Kentucky
145.959
28
138.616
28
131.839
29
Oklahoma
134.651
29
121.558
30
111.400
30
Iowa
123.970
30
117.635
29
111.626
31
Nevada
118.399
31
110.158
31
99.342
32
Kansas
111.699
32
105.228
32
99.125
33
Utah
97.749
33
88.364
34
81.059
34
Arkansas
91.837
34
87.004
33
81.752
Washington D.C.
87.664
82.628
77.782
35
Mississippi
84.225
35
79.786
35
76.534
36
New Mexico
75.910
37
69.692
37
63.861
37
Nebraska
75.700
36
72.242
36
67.976
38
Delaware
60.361
38
56.731
38
52.454
39
Hawaii
58.307
39
54.773
40
50.781
40
New Hampshire
56.276
40
54.119
39
51.656
41
Tây Virginia
55.658
41
53.091
41
49.903
42
Idaho
49.907
42
45.891
43
42.697
43
Maine
46.973
43
44.906
42
43.131
44
Rhode Island
45.660
44
43.623
44
42.213
45
Alaska
41.105
45
39.394
45
34.729
46
Nam Dakota
32.330
46
30.541
46
29.519
47
Montana
32.322
47
29.915
47
27.790
48
Wyoming
29.561
48
27.246
48
23.876
49
Bắc Dakota
26.385
49
24.935
49
22.715
50
Vermont
24.213
50
23.056
50
22.002
Xem thêm
[
sửa
|
sửa mã nguồn
]
Danh sách các tiểu bang Hoa Kỳ theo GDP trên đầu người (danh nghĩa)
Nguồn
[
sửa
|
sửa mã nguồn
]
Thống kê của BEA về GDP trong khoảng 1997-2006
^
US Government Revenue
x
t
s
Những danh sách về các
tiểu bang
Hoa Kỳ
Cách viết tắt
·
Các luật về rượu cồn
·
Diện tích
·
Các thủ phủ
·
Các tòa quốc hội
·
Các quận
·
Ngày trở thành tiểu bang
·
Độ cao
·
Mã FIPS
·
GDP
(
trên đầu người
)
·
Phát triển dân số
·
Chỉ số phát triển con người
·
Thành phố lớn nhất
·
Tuổi thọ trung bình
·
Lương tối thiểu
·
Nguồn gốc tên
·
Chưa từng là lãnh thổ
·
Thừa cân
·
Dân số
(
thành thị
) (
mật độ
)
·
Tỉ lệ nghèo
·
Luật hôn nhân đồng tính
(
tình trạng
)
·
Luật cấm hút thuốc
·
Luật tiểu bang
·
Tòa nhà cao nhất
·
Mức thu thuế (
tiểu bang
) (
liên bang
)
·
Múi giờ
·
Tỷ lệ thất nghiệp
Lấy từ “
http://vi.wikipedia.org/w/index.php?title=Danh_sách_các_tiểu_bang_Hoa_Kỳ_theo_GDP_(danh_nghĩa)&oldid=14700654
”
Thể loại
:
Kinh tế Hoa Kỳ
Danh sách có liên quan đến các tiểu bang Hoa Kỳ
Tổng sản phẩm nội địa
Trình đơn chuyển hướng
Công cụ cá nhân
Mở tài khoản
Đăng nhập
Không gian tên
Bài viết
Thảo luận
Biến thể
Các hiển thị
Đọc
Sửa đổi
Sửa mã nguồn
Xem lịch sử
Khác
Tìm kiếm
Xem nhanh
Trang Chính
Nội dung chọn lọc
Tin tức
Bài viết ngẫu nhiên
Thay đổi gần đây
Quyên góp
Tương tác
Hướng dẫn
Giới thiệu Wikipedia
Cộng đồng
Thảo luận chung
Giúp sử dụng
Công cụ
Các liên kết đến đây
Thay đổi liên quan
Các trang đặc biệt
Liên kết thường trực
Thông tin trang
Khoản mục Wikidata
Trích dẫn trang này
In/xuất ra
Tạo một quyển sách
Tải về dưới dạng PDF
Bản để in ra
Ngôn ngữ khác
English
Español
Português
Simple English
اردو
中文
Sửa liên kết
Trang này được sửa đổi lần cuối lúc 08:15, ngày 13 tháng 12 năm 2013.
Văn bản được phát hành theo
Giấy phép Creative Commons Ghi công/Chia sẻ tương tự
; có thể áp dụng điều khoản bổ sung. Xem
Điều khoản Sử dụng
để biết thêm chi tiết.
Wikipedia® là thương hiệu đã đăng ký của
Wikimedia Foundation, Inc.
, một tổ chức phi lợi nhuận.
Quy định quyền riêng tư
Giới thiệu Wikipedia
Lời phủ nhận
Nhà phát triển
Phiên bản di động

markdown:
# Danh sách các tiểu bang Hoa Kỳ theo GDP (danh nghĩa)
Bách khoa toàn thư mở Wikipedia
|GDP
|
Hạng
|Bang
|
lãnh thổ
|GDP
|
(triệu
|Tỷ lệ so với
|
GDP quốc gia
|Dân số
|
(triệu)
|GDP
|
trên người ($)
|Hạng GDP
|
trên người
|
|![]()
|16.202.700||100,00||316,8||47.482|
|1||
|![]()
|2.080.600||13,34||37,3||51.914||13|
|2||
|![]()
|1.458.300||8,92||25,1||58.099||7|
|3||
|![]()
|1.156.500||7,68||19,4||57.423||8|
|4||
|![]()
|754.000||5,20||18,8||40.106||40|
|5||
|![]()
|644.200||4,44||12,8||50.328||16|
|6||
|![]()
|575.600||3,97||12,7||45.323||25|
|7||
|![]()
|497.000||3,42||8,8||56.477||9|
|8||
|![]()
|483.400||3,33||11,5||42.035||33|
|9||
|![]()
|427.700||2,95||8,0||53.463||10|
|10||
|![]()
|407.400||2,81||9,5||42.884||31|
|11||
|![]()
|403.100||2,79||9,7||41.711||35|
|12||
|![]()
|377.700||2,60||6,5||58.108||6|
|13||
|![]()
|372.400||2,57||9,9||37.616||42|
|14||
|![]()
|351.100||2,42||6,7||52.403||11|
|15||
|![]()
|300.000||2,07||5,8||51.724||14|
|16||
|![]()
|267.600||1,84||6,5||41.169||36|
|17||
|![]()
|267.100||1,84||5,3||50.396||15|
|18||
|![]()
|261.300||1,80||6,4||40.828||39|
|19||
|![]()
|259.700||1,79||5,0||51.940||12|
|20||
|![]()
|251.400||1,73||5,7||44.105||29|
|21||
|![]()
|250.300||1,72||6,3||39.730||41|
|22||
|![]()
|246.700||1,70||6,0||41.117||37|
|23||
|![]()
|233.400||1,61||3,6||64.833||4|
|24||
|![]()
|213.600||1,47||4,5||47.467||22|
|25||
|![]()
|174.400||1,20||4,8||36.333||46|
|26||
|![]()
|168.900||1,16||3,8||44.447||27|
|27||
|![]()
|164.300||1,13||4,6||35.717||48|
|28||
|![]()
|161.400||1,11||4,3||37.535||43|
|29||
|![]()
|160.500||1,11||3,8||42.237||32|
|30||
|![]()
|147.200||1,01||3,0||49.067||20|
|31||
|![]()
|128.500||0,89||2,9||44.310||28|
|32||
|![]()
|127.500||0,88||2,7||47.222||24|
|33||
|![]()
|116.900||0,81||2,8||41.750||34|
|34||
|![]()
|105.800||0,73||2,9||36.483||45|
|35||
|![]()
|104.700||0,72||0,6||174.500||1|
|36||
|![]()
|98.900||0,68||3,0||32.967||51|
|37||
|![]()
|89.600||0,62||1,8||49.778||18|
|38||
|![]()
|75.500||0,52||2,1||35.952||47|
|39||
|![]()
|68.900||0,47||1,4||49.214||19|
|40||
|![]()
|66.600||0,46||1,9||35.053||49|
|41||
|![]()
|62.700||0,43||0,9||69.667||2|
|42||
|![]()
|61.600||0,42||1,3||47.385||23|
|43||
|![]()
|54.800||0,38||1,6||34.250||50|
|44||
|![]()
|53.200||0,37||1,3||40.923||38|
|45||
|![]()
|49.500||0,34||1,1||45.000||26|
|46||
|![]()
|45.600||0,31||0,7||65.143||3|
|47||
|![]()
|39.900||0,27||0,8||49.875||17|
|48||
|![]()
|38.200||0,26||0,6||63.667||5|
|49||
|![]()
|37.200||0,26||1,0||37.200||44|
|50||
|![]()
|33.400||0,23||0,7||47.714||21|
|51||
|![]()
|26.400||0,18||0,6||44.000||30|
|2006
|
Xếp hạng
|Tiểu bang||Tổng sản phẩm 2006
|
(triệu
|2005
|
Xếp hạng
|Tổng sản phẩm 2005
|
(triệu
|2004
|
Xếp hạng
|Tổng sản phẩm2004
|
(triệu
|1||
|[Texas](/wiki/Texas) [New York](/wiki/Th%C3%A0nh_ph%E1%BB%91_New_York) [Florida](/wiki/Florida) [Illinois](/wiki/Illinois) [Pennsylvania](/wiki/Pennsylvania) [Ohio](/wiki/Ohio) [New Jersey](/wiki/New_Jersey) [Michigan](/wiki/Michigan) [Georgia](/wiki/Georgia,_Hoa_K%E1%BB%B3) [Bắc Carolina](/wiki/B%E1%BA%AFc_Carolina) [Virginia](/wiki/Virginia) [Massachusetts](/wiki/Massachusetts) [Washington](/wiki/Washington_(ti%E1%BB%83u_bang)) [Maryland](/wiki/Maryland) [Indiana](/wiki/Indiana) [Minnesota](/wiki/Minnesota) [Tennessee](/wiki/Tennessee) [Arizona](/wiki/Arizona) [Colorado](/wiki/Colorado) [Wisconsin](/wiki/Wisconsin) [Missouri](/wiki/Missouri) [Connecticut](/wiki/Connecticut) [Louisiana](/wiki/Louisiana) [Alabama](/wiki/Alabama) [Oregon](/wiki/Oregon) [Nam Carolina](/wiki/Nam_Carolina) [Kentucky](/wiki/Kentucky) [Oklahoma](/wiki/Oklahoma) [Iowa](/wiki/Iowa) [Nevada](/wiki/Nevada) [Kansas](/wiki/Kansas) [Utah](/wiki/Utah) [Arkansas](/wiki/Arkansas) [Washington D.C.](/wiki/Washington,_D.C.) [Mississippi](/wiki/Mississippi) [New Mexico](/wiki/New_Mexico) [Nebraska](/wiki/Nebraska) [Delaware](/wiki/Delaware) [Hawaii](/wiki/Hawaii) [New Hampshire](/wiki/New_Hampshire) [Tây Virginia](/wiki/T%C3%A2y_Virginia) [Idaho](/wiki/Idaho) [Maine](/wiki/Maine) [Rhode Island](/wiki/Rhode_Island) [Alaska](/wiki/Alaska) [Nam Dakota](/wiki/Nam_Dakota) [Montana](/wiki/Montana) [Wyoming](/wiki/Wyoming) [Bắc Dakota](/wiki/B%E1%BA%AFc_Dakota) [Vermont](/wiki/Vermont)
## Xem thêm[
[sửa](/w/index.php?title=Danh_s%C3%A1ch_c%C3%A1c_ti%E1%BB%83u_bang_Hoa_K%E1%BB%B3_theo_GDP_(danh_ngh%C4%A9a)&veaction=edit&vesection=1) | [sửa mã nguồn](/w/index.php?title=Danh_s%C3%A1ch_c%C3%A1c_ti%E1%BB%83u_bang_Hoa_K%E1%BB%B3_theo_GDP_(danh_ngh%C4%A9a)&action=edit§ion=1)]
## Nguồn[
[sửa](/w/index.php?title=Danh_s%C3%A1ch_c%C3%A1c_ti%E1%BB%83u_bang_Hoa_K%E1%BB%B3_theo_GDP_(danh_ngh%C4%A9a)&veaction=edit&vesection=2) | [sửa mã nguồn](/w/index.php?title=Danh_s%C3%A1ch_c%C3%A1c_ti%E1%BB%83u_bang_Hoa_K%E1%BB%B3_theo_GDP_(danh_ngh%C4%A9a)&action=edit§ion=2)]
|
|

WARC-Type: response

Content-Type: application/http; msgtype=response

Server: Apache

X-Content-Type-Options: nosniff

Content-language: vi

X-UA-Compatible: IE=Edge

Content-Encoding: gzip

Content-Type: text/html; charset=UTF-8

Vary: Accept-Encoding,Cookie,X-Use-HHVM

Via: 1.1 varnish, 1.1 varnish

Accept-Ranges: bytes

Connection: close

X-Cache: cp1067 miss (0), cp1067 frontend miss (0)

Cache-Control: private, s-maxage=0, max-age=0, must-revalidate

X-Analytics: php=zend


text:
Dracon
Dracon ( /ˈdreɪkoʊ/; tiếng Hy Lạp: Δράκων, Drakōn) (?-?) là nhà lập pháp Hy Lạp cổ đại đầu tiên của thành bang Athen, sống vào thế kỷ thứ 7 trước công nguyên. Ông là người đã thay thế toàn bộ hệ thống luật pháp truyền miệng lâu đời bằng một thứ luật pháp thành văn cực kỳ hà khắc được thực thi chỉ bởi một quan tòa duy nhất. Từ những việc Dracon làm, sau này tiếng Anh có thêm từ draconian để chỉ sự tàn bạo được sử dụng để mô tả những đạo luật hà khắc.
Tiểu sử[sửa | sửa mã nguồn]
Suốt kỳ Olympiad lần thứ 39, vào năm 621 TCN, nhà lập pháp Dracon cho ban hành một bộ luật hợp pháp thành văn đầu tiên tại thành bang Athen. Những nguồn tài liệu cổ xưa lẫn hiện nay đều không biết rõ chi tiết về cuộc đời của ông. Có giả thuyết nêu rằng ông thuộc về giới quý tộc Hy Lạp ở deme (thành phố nhỏ ở Attica vào thời Hy Lạp cổ đại) với tên gọi là Eupatridae. Một tập hồ sơ cổ của Suda có ghi chép về ông vào thế kỷ 10, trước thời đại của Bảy nhà hiền triết Hy Lạp. Nó cũng có liên quan đến câu chuyện dân gian về cái chết của ông tại nhà hát Aeginetan.[1] Trong buổi phê chuẩn chính thức một buổi biểu diễn theo truyền thống Hy Lạp cổ đại, người ủng hộ ông đã "ném khá nhiều mũ, áo và áo choàng trên đầu của ông khiến ông chết ngạt, và được chôn cất ở đó cùng một nhà hát".[2] Aristotle còn ghi rõ Dracon đã trình bộ luật hợp pháp mới này trước các quan chấp chính của Aristaechmus (Ἀρισταίχμος) vào năm 621 TCN.[3]
Đạo luật hà khắc[sửa | sửa mã nguồn]
Bộ luật (θεσμοί - thesmi) mà ông ban hành chính là bộ luật thành văn đầu tiên của Athen. Vì không có ai biết rõ sự tồn tài của bộ luật mới này, nên chúng được dán lên một cái bảng gỗ (άξονες - axones), tự xoay quanh trục để mọi người có thể đọc được bất kỳ mặt nào, chúng được lưu giữ suốt khoảng hơn hai thế kỷ, trên một tấm bia đá hình chóp (κύρβεις - kirvis). Hiếp pháp này có vài điểm mới như sau:
- Thay vì luật pháp bằng miệng được biết đến với việc tự ý áp dụng và giải thích tất cả các đạo luật được viết ra do đó làm cho mọi công dân biết đọc biết viết có thể kháng cáo lên Areopagus (Hội đồng Hy Lạp) cho những bất công của họ.
[...] Đạo luật do Dracon ban hành, khi những quy tắc của bộ luật được soạn thảo. (Aristotle: Athenian Constitution, Part 5, Section 41)
- Luật còn phân biệt giữa tội giết người và vô ý giết người.
Tuy nhiên bộ luật này đặc biệt cực kỳ khắc nghiệt. Ví dụ như con nợ nào có địa vị thấp hơn so với chủ nợ thì bị buộc làm nô lệ, hình phạt tỏ ra khoan dung hơn đối với những khoản nợ của một thành viên thuộc tầng lớp thấp hơn. Ngoài ra nó còn dành án tử hình cho cả những tội nhỏ nhất tới mức người ta nói rằng luật pháp của Dracon được viết bằng máu chứ không phải mực. Liên quan đến việc tự do sử dụng án tử hình trong luật pháp của Dracon, Plutarch ghi rằng:
- Khi có người hỏi vì sao lại ban hành những đạo luật hà khắc như vậy, Dracon trả lời: Chúng ta cần án tử hình để ngăn chặn những tội ác nhỏ, còn những tội lớn hơn thì ta chưa nghĩ ra hình phạt nào năng hơn thế..[4]
Về sau nhà lập pháp Solon đã cho hủy bỏ luật pháp của Dracon, chỉ giữ nguyên án tử hình đối với tội giết người.
Xem thêm[sửa | sửa mã nguồn]
Tài liệu tham khảo[sửa | sửa mã nguồn]
- ^ Cobham, Ebenezer. The reader's handbook of allusions, references, plots and stories, p.451.
- ^ Suidas. "Δράκων", Suda On Line, Adler number delta, 1495.
- ^ Aristotle. The Athenian Constitution.
- ^ Plutarch, Những Anh Hùng Hy Lạp Cổ Đại, NXB Trẻ (2003), trang 54.
Đọc thêm[sửa | sửa mã nguồn]
- Carawan, Edwin. Rhetoric and the Law of Draco. New York: Oxford University Press, 1998.
- Gagarin, Michael. Drakon and Early Athenian Homicide Law. New Haven: Yale University Press, 1981.
- Gagarin, Michael and David Cohen., eds. The Cambridge Companion to Ancient Greek Law. Cambridge: Cambridge University Press, 2005.
- Maine, Sir Henry Sumner. Ancient Law. Boston: Beacon Press, 1963.
- Phillips, David. Avengers of Blood: Homicide in Athenian Law and Custom from Draco to Demosthenes. Stuttgart: Steiner, 2008.
- Stroud, Ronald S. Drakon's Law on Homicide. Berkeley: University of California Press, 1968.

markdown:
# Dracon
|
|![]()
|
|Đây là một bài
Xin hãy tạo liên kết đến bài này trong các bài của các
(tháng 2 2013)
|Dracon|
|Sinh||Khoảng năm
|[Athen](/wiki/Athena), [Hy Lạp](/wiki/Hy_L%E1%BA%A1p) **Dracon** ( [/](//en.wikipedia.org/wiki/Help:IPA_for_English) [ˈ](//en.wikipedia.org/wiki/Wikipedia:IPA_for_English#Key) [d](//en.wikipedia.org/wiki/Wikipedia:IPA_for_English#Key) [r](//en.wikipedia.org/wiki/Wikipedia:IPA_for_English#Key) [eɪ](//en.wikipedia.org/wiki/Wikipedia:IPA_for_English#Key) [k](//en.wikipedia.org/wiki/Wikipedia:IPA_for_English#Key) [oʊ](//en.wikipedia.org/wiki/Wikipedia:IPA_for_English#Key) [/](//en.wikipedia.org/wiki/Help:IPA_for_English); [tiếng Hy Lạp](/wiki/Ti%E1%BA%BFng_Hy_L%E1%BA%A1p): *Δράκων*, *Drakōn*) (?-?) là [nhà lập pháp](/w/index.php?title=Nh%C3%A0_l%E1%BA%ADp_ph%C3%A1p&action=edit&redlink=1) [Hy Lạp cổ đại](/wiki/Hy_L%E1%BA%A1p_c%E1%BB%95_%C4%91%E1%BA%A1i) đầu tiên của [thành bang Athen](/wiki/Athena), sống vào [thế kỷ thứ 7 trước công nguyên](/w/index.php?title=Th%E1%BA%BF_k%E1%BB%B7_th%E1%BB%A9_7_tr%C6%B0%E1%BB%9Bc_c%C3%B4ng_nguy%C3%AAn&action=edit&redlink=1). Ông là người đã thay thế toàn bộ hệ thống [luật pháp truyền miệng](/w/index.php?title=Lu%E1%BA%ADt_ph%C3%A1p_truy%E1%BB%81n_mi%E1%BB%87ng&action=edit&redlink=1) lâu đời bằng một thứ [luật pháp thành văn](/w/index.php?title=Lu%E1%BA%ADt_ph%C3%A1p_th%C3%A0nh_v%C4%83n&action=edit&redlink=1) cực kỳ hà khắc được thực thi chỉ bởi một quan tòa duy nhất. Từ những việc Dracon làm, sau này tiếng Anh có thêm từ *draconian* để chỉ sự tàn bạo được sử dụng để mô tả những đạo luật hà khắc.
## Tiểu sử[
[sửa](/w/index.php?title=Dracon&veaction=edit&vesection=1) | [sửa mã nguồn](/w/index.php?title=Dracon&action=edit§ion=1)]
Suốt kỳ
[Olympiad](/w/index.php?title=Olympiad&action=edit&redlink=1) lần thứ 39, vào năm [621 TCN](/w/index.php?title=621_TCN&action=edit&redlink=1), nhà lập pháp Dracon cho ban hành một bộ luật hợp pháp thành văn đầu tiên tại thành bang Athen. Những nguồn tài liệu cổ xưa lẫn hiện nay đều không biết rõ chi tiết về cuộc đời của ông. Có giả thuyết nêu rằng ông thuộc về giới quý tộc Hy Lạp ở [deme](/w/index.php?title=Deme&action=edit&redlink=1) (thành phố nhỏ ở [Attica](/wiki/Attica) vào thời Hy Lạp cổ đại) với tên gọi là [Eupatridae](/w/index.php?title=Eupatridae&action=edit&redlink=1). Một tập hồ sơ cổ của [Suda](/w/index.php?title=Suda&action=edit&redlink=1) có ghi chép về ông vào thế kỷ 10, trước thời đại của [Bảy nhà hiền triết Hy Lạp](/w/index.php?title=B%E1%BA%A3y_nh%C3%A0_hi%E1%BB%81n_tri%E1%BA%BFt_Hy_L%E1%BA%A1p&action=edit&redlink=1). Nó cũng có liên quan đến câu chuyện dân gian về cái chết của ông tại nhà hát [Aeginetan](/w/index.php?title=Aeginetan&action=edit&redlink=1). Trong buổi phê chuẩn chính thức một buổi biểu diễn theo truyền thống Hy Lạp cổ đại, người ủng hộ ông đã " [1] *ném khá nhiều mũ, áo và áo choàng trên đầu của ông khiến ông chết ngạt, và được chôn cất ở đó cùng một nhà hát*". [[2]](#cite_note-2) [Aristotle](/wiki/Aristoteles)còn ghi rõ Dracon đã trình bộ luật hợp pháp mới này trước các quan chấp chính của [Aristaechmus](/w/index.php?title=Aristaechmus&action=edit&redlink=1)(Ἀρισταίχμος) vào năm 621 TCN. [[3]](#cite_note-3)
## Đạo luật hà khắc[
[sửa](/w/index.php?title=Dracon&veaction=edit&vesection=2) | [sửa mã nguồn](/w/index.php?title=Dracon&action=edit§ion=2)] [Bộ luật](/w/index.php?title=B%E1%BB%99_lu%E1%BA%ADt&action=edit&redlink=1) (θεσμοί - thesmi) mà ông ban hành chính là bộ luật thành văn đầu tiên của Athen. Vì không có ai biết rõ sự tồn tài của bộ luật mới này, nên chúng được dán lên một cái bảng gỗ (άξονες - axones), tự xoay quanh trục để mọi người có thể đọc được bất kỳ mặt nào, chúng được lưu giữ suốt khoảng hơn hai thế kỷ, trên một tấm [bia đá](/w/index.php?title=Bia_%C4%91%C3%A1&action=edit&redlink=1) hình chóp (κύρβεις - kirvis). Hiếp pháp này có vài điểm mới như sau:
- Thay vì luật pháp bằng miệng được biết đến với việc tự ý áp dụng và giải thích tất cả các đạo luật được viết ra do đó làm cho mọi công dân biết đọc biết viết có thể kháng cáo lên Areopagus (Hội đồng Hy Lạp) cho những bất công của họ.
[...] Đạo luật do Dracon ban hành, khi những quy tắc của bộ luật được soạn thảo. (
[Aristotle]: [Athenian Constitution], [Part 5, Section 41])
- Luật còn phân biệt giữa tội
[giết người](/wiki/Gi%E1%BA%BFt_ng%C6%B0%E1%BB%9Di)và [vô ý giết người](/w/index.php?title=V%C3%B4_%C3%BD_gi%E1%BA%BFt_ng%C6%B0%E1%BB%9Di&action=edit&redlink=1).
Tuy nhiên bộ luật này đặc biệt cực kỳ khắc nghiệt. Ví dụ như
[con nợ](/w/index.php?title=Con_n%E1%BB%A3&action=edit&redlink=1) nào có địa vị thấp hơn so với [chủ nợ](/w/index.php?title=Ch%E1%BB%A7_n%E1%BB%A3&action=edit&redlink=1) thì bị buộc làm [nô lệ](/wiki/N%C3%B4_l%E1%BB%87), hình phạt tỏ ra khoan dung hơn đối với những khoản nợ của một thành viên thuộc tầng lớp thấp hơn. Ngoài ra nó còn dành án [tử hình](/wiki/T%E1%BB%AD_h%C3%ACnh) cho cả những tội nhỏ nhất tới mức người ta nói rằng luật pháp của Dracon được viết bằng máu chứ không phải mực. Liên quan đến việc tự do sử dụng án tử hình trong luật pháp của Dracon, [Plutarch](/wiki/Plutarchus) ghi rằng: *Khi có người hỏi vì sao lại ban hành những đạo luật hà khắc như vậy, Dracon trả lời: Chúng ta cần án tử hình để ngăn chặn những tội ác nhỏ, còn những tội lớn hơn thì ta chưa nghĩ ra hình phạt nào năng hơn thế..* [[4]](#cite_note-4)
Về sau nhà lập pháp
[Solon](/w/index.php?title=Solon&action=edit&redlink=1) đã cho hủy bỏ luật pháp của Dracon, chỉ giữ nguyên án tử hình đối với tội giết người.
## Xem thêm[
[sửa](/w/index.php?title=Dracon&veaction=edit&vesection=3) | [sửa mã nguồn](/w/index.php?title=Dracon&action=edit§ion=3)]
|
|![]()
*trong từ điển mở tiếng Việt* [draconian](//vi.wiktionary.org/wiki/draconian) [Wiktionary](/wiki/Wiktionary)
## Tài liệu tham khảo[
[sửa](/w/index.php?title=Dracon&veaction=edit&vesection=4) | [sửa mã nguồn](/w/index.php?title=Dracon&action=edit§ion=4)] **Cobham, Ebenezer.** [^](#cite_ref-1) [, p.451.](http://books.google.com/books?oe=UTF-8&id=fzoFAAAAYAAJ&q=draco#search_anchor) *The reader's handbook of allusions, references, plots and stories* **Suidas. "** [^](#cite_ref-2) [Δράκων](http://www.stoa.org/sol-bin/search.pl?login=guest&enlogin=guest&db=REAL&field=adlerhw_gr&searchstr=delta,1495&filter=CD-Unicode)", *Suda On Line*, Adler number delta, 1495. **Aristotle.** [^](#cite_ref-3) *The Athenian Constitution.* **Plutarch, Những Anh Hùng Hy Lạp Cổ Đại, NXB Trẻ (2003), trang 54.** [^](#cite_ref-4)
## Đọc thêm[
[sửa](/w/index.php?title=Dracon&veaction=edit&vesection=5) | [sửa mã nguồn](/w/index.php?title=Dracon&action=edit§ion=5)]
- Carawan, Edwin.
*Rhetoric and the Law of Draco*. New York: Oxford University Press, 1998.
- Gagarin, Michael.
*Drakon and Early Athenian Homicide Law*. New Haven: Yale University Press, 1981.
- Gagarin, Michael and David Cohen., eds.
*The Cambridge Companion to Ancient Greek Law*. Cambridge: Cambridge University Press, 2005.
- Maine, Sir Henry Sumner.
*Ancient Law*. Boston: Beacon Press, 1963.
- Phillips, David.
*Avengers of Blood: Homicide in Athenian Law and Custom from Draco to Demosthenes*. Stuttgart: Steiner, 2008.
- Stroud, Ronald S.
*Drakon's Law on Homicide*. Berkeley: University of California Press, 1968.

X-Cache: cp1053 miss (0), cp1067 frontend miss (0)


text:
Ngô Thanh Nguyên
Go Seigen hay Ngô Thanh Nguyên (吳清源, Pinyin: Wú Qīngyuán) sinh ngày 19 tháng 5 năm 1914,tại Phúc Kiến, Trung Quốc. Tên ban đầu của ông là Wu Quan. Nhưng ông được mọi người ở phương Tây biết đến với tên Go Seigen, là nhà Trung Quốc học và kỳ thủ cờ vây ở Nhật Bản. Ông được nhiều người coi là kỳ thủ cờ vây mạnh nhất thế kỷ 20.
Tiểu sử[sửa | sửa mã nguồn]
Go Seigen sinh ngày 19/5/1914 tại Phúc Châu, tỉnh Phúc Kiến, Trung Hoa. Ông bắt đầu chơi cờ vây rất trễ, 9 tuổi, so với các kỳ thủ chuyên nghiệp (Honinbo Dosaku học lúc 7 tuổi, Honinbo Shusaku trước khi được 6 tuổi). Go Seigen đến với cờ vây qua những bài học của cha mình, học trò của Honinbo Shuho khi du học tại Nhật Bản, và ông nhanh chóng thể hiện năng khiếu cờ vây của mình.
Khi được 12 tuổi, sức cờ của ông được thể hiện như một kỳ thủ chuyên nghiệp trong trận đấu với Iwamoto Kaoru, 6p vào năm 1926.
Năm sau đó, ông đã thủ hòa được với Inoue Kohei, 5p trong 2 trận. Vào năm 1928, lúc được 14 tuổi, ổng đã 2 lần thắng được kỳ thủ chuyên nghiệp Hashimoto Utaro, 4p. Từ đó, danh tiếng của ông đã lan đến Nhật Bản, quốc gia có trình độ cờ vây cao nhất thế giới lúc bấy giờ, một cuộc vận động được bắt đầu để chuyển (bring) ông đến Nhật Bản. Go Seigen di cư đến Nhật Bản vào năm 1928 theo lời mời của Baron Kihachiro Okura và Inukai Tsuyoshi (sau này là thủ tướng Nhật Bản) và bắt đầu vào con đường chuyên nghiệp. Segoe Kensaku, Hashimoto Utaro và Cho Hunhyun là các vị thầy của ông trong thời gian này.
Từ đó, Go Seigen sớm bắt đầu tiến dần lên các vị trí cao trong giới chuyên nghiệp. Khi được 18 tuổi, ông đã ở một vị trí khá cao, và rất hiếm có các kỳ thủ có trình độ tương tự. Vào năm 1933, cùng với bạn của mình là Kitani Minoru đã phát triển những khai cuộc kiểu mới (Shinfuseki), phá vỡ các nguyên tắc khai cuộc đã lỗi thời. Và đó là cống hiến quan trọng nhất mà Go Seigen cùng với Kitani Monoru đã thực hiện được, cả hai đều được thừa nhận là cha đẻ của cờ vây hiện đại.
Bắt đầu từ năm 1939, Go Seigen bắt đầu một loạt trận đấu ngoạn mục trong những trận đấu Jubango với các kỳ thủ cờ vây cấp cao, chứng tỏ trình độ và ưu thế áp đảo của ông một cách thuyết phục.
Go Segen chỉ có duy nhất một học trò, Rin Kaiho - Thiên Nguyên danh dự.
Sự nghiệp cờ vây của ông bắt đầu đi xuống vào những năm 1960 vì lý do sức khỏe, và ông đã giã từ giới chuyên nghiệp vào năm 1964. Tuy vậy, ông vẫn tiếp tục các hoạt động liên quan đến cờ vây như giảng dạy, viết sách và phát triển cờ vây trên toàn thế giới.

markdown:
# Ngô Thanh Nguyên
**Go Seigen** hay **Ngô Thanh Nguyên** (吳清源, [Pinyin](/wiki/B%C3%ADnh_%C3%A2m_H%C3%A1n_ng%E1%BB%AF): Wú Qīngyuán) sinh ngày [19 tháng 5](/wiki/19_th%C3%A1ng_5) năm [1914](/wiki/1914),tại [Phúc Kiến](/wiki/Ph%C3%BAc_Ki%E1%BA%BFn), [Trung Quốc](/wiki/Trung_Qu%E1%BB%91c). Tên ban đầu của ông là Wu Quan. Nhưng ông được mọi người ở phương Tây biết đến với tên Go Seigen, là nhà [Trung Quốc](/wiki/Trung_Qu%E1%BB%91c) học và kỳ thủ [cờ vây](/wiki/C%E1%BB%9D_v%C3%A2y) ở [Nhật Bản](/wiki/Nh%E1%BA%ADt_B%E1%BA%A3n). Ông được nhiều người coi là kỳ thủ cờ vây mạnh nhất thế kỷ 20.
## Tiểu sử[
[sửa](/w/index.php?title=Ng%C3%B4_Thanh_Nguy%C3%AAn&veaction=edit&vesection=1) | [sửa mã nguồn](/w/index.php?title=Ng%C3%B4_Thanh_Nguy%C3%AAn&action=edit§ion=1)]
Go Seigen sinh ngày 19/5/1914 tại
[Phúc Châu](/wiki/Ph%C3%BAc_Ch%C3%A2u), tỉnh [Phúc Kiến](/wiki/Ph%C3%BAc_Ki%E1%BA%BFn), [Trung Hoa](/wiki/T%C3%AAn_g%E1%BB%8Di_Trung_Qu%E1%BB%91c). Ông bắt đầu chơi cờ vây rất trễ, 9 tuổi, so với các kỳ thủ chuyên nghiệp ( [Honinbo Dosaku](/w/index.php?title=Honinbo_Dosaku&action=edit&redlink=1) học lúc 7 tuổi, [Honinbo Shusaku](/w/index.php?title=Honinbo_Shusaku&action=edit&redlink=1) trước khi được 6 tuổi). Go Seigen đến với cờ vây qua những bài học của cha mình, học trò của [Honinbo Shuho](/w/index.php?title=Honinbo_Shuho&action=edit&redlink=1) khi du học tại [Nhật Bản](/wiki/Nh%E1%BA%ADt_B%E1%BA%A3n), và ông nhanh chóng thể hiện năng khiếu cờ vây của mình.
Khi được 12 tuổi, sức cờ của ông được thể hiện như một kỳ thủ chuyên nghiệp trong trận đấu với
[Iwamoto Kaoru](/w/index.php?title=Iwamoto_Kaoru&action=edit&redlink=1), 6p vào năm 1926.
Năm sau đó, ông đã thủ hòa được với
[Inoue Kohei](/w/index.php?title=Inoue_Kohei&action=edit&redlink=1), 5p trong 2 trận. Vào năm 1928, lúc được 14 tuổi, ổng đã 2 lần thắng được kỳ thủ chuyên nghiệp [Hashimoto Utaro](/w/index.php?title=Hashimoto_Utaro&action=edit&redlink=1), 4p. Từ đó, danh tiếng của ông đã lan đến Nhật Bản, quốc gia có trình độ cờ vây cao nhất thế giới lúc bấy giờ, một cuộc vận động được bắt đầu để chuyển ( *bring*) ông đến Nhật Bản. Go Seigen di cư đến Nhật Bản vào năm 1928 theo lời mời của [Baron Kihachiro Okura](/w/index.php?title=Baron_Kihachiro_Okura&action=edit&redlink=1) và [Inukai Tsuyoshi](/w/index.php?title=Inukai_Tsuyoshi&action=edit&redlink=1) (sau này là thủ tướng Nhật Bản) và bắt đầu vào con đường chuyên nghiệp. Segoe Kensaku, Hashimoto Utaro và Cho Hunhyun là các vị thầy của ông trong thời gian này.
Từ đó, Go Seigen sớm bắt đầu tiến dần lên các vị trí cao trong giới chuyên nghiệp. Khi được 18 tuổi, ông đã ở một vị trí khá cao, và rất hiếm có các kỳ thủ có trình độ tương tự. Vào năm 1933, cùng với bạn của mình là
[Kitani Minoru](/wiki/Kitani_Minoru) đã phát triển những khai cuộc kiểu mới (Shinfuseki), phá vỡ các nguyên tắc khai cuộc đã lỗi thời. Và đó là cống hiến quan trọng nhất mà Go Seigen cùng với Kitani Monoru đã thực hiện được, cả hai đều được thừa nhận là cha đẻ của cờ vây hiện đại.
Bắt đầu từ năm 1939, Go Seigen bắt đầu một loạt trận đấu ngoạn mục trong những trận đấu
[Jubango](/w/index.php?title=Jubango&action=edit&redlink=1) với các kỳ thủ cờ vây cấp cao, chứng tỏ trình độ và ưu thế áp đảo của ông một cách thuyết phục.
Go Segen chỉ có duy nhất một học trò,
[Rin Kaiho](/w/index.php?title=Rin_Kaiho&action=edit&redlink=1) - Thiên Nguyên danh dự.
Sự nghiệp cờ vây của ông bắt đầu đi xuống vào những năm 1960 vì lý do sức khỏe, và ông đã giã từ giới chuyên nghiệp vào năm 1964. Tuy vậy, ông vẫn tiếp tục các hoạt động liên quan đến cờ vây như giảng dạy, viết sách và phát triển cờ vây trên toàn thế giới.

X-Cache: cp1066 hit (1), cp1065 frontend miss (0)