SlideShare a Scribd company logo
1 of 18
Trần Tiến Hiển-TATA Consultancy Services

CÚ PHÁP NGÔN NGỮ
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
Cú pháp
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ụ
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>;
stdio.h
int add(int x, int y)
{
return x + y;

//Chú giải: dòng này khai báo tập tin bao gồm là
Trần Tiến Hiển-TATA Consultancy Services
}
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
<code>return</code>
hoàn toàn có thể dùng các câu lệnh khác đơn giản hơn. */
}
int main(void)
{
int z = 1;
int y = -2;
printf("%d + 1 = %dn", z, add(z, 1));
printf ("absolute value of %d is %d", y, abs(y));
return 0;
}
Chú ý: phần mã trên đã được thử thành công dùng trình dịch GNU (cho ANSI C và C99)

Mô tả
Trong các câu lệnh tiền xử lý, ở cấp độ cao nhất, một chương trình ngôn ngữ C luôn có một
chuỗi các khai báo cho các tập tin bao gồm.
Sau đó là các khai báo của phạm vi tập tin. Các khai báo này giới thiệu các hàm, các biến và các
kiểu biến. Các hàm trong C nhìn tương tự với các chương trình con của Fortran hay các thủ tục
của Pascal. Định nghĩa của hàm xuất hiện trong phần thân của nó (phần giữa bộ dấu ngoặc { 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ư
Trần Tiến Hiển-TATA Consultancy Services

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
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 <code>main<code> 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));
*p = n;
}

// đăng kí một vùng nhớ
// 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;
}

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.
int **p
Trần Tiến Hiển-TATA Consultancy Services

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
Một cách cơ bản thì C là ngôn ngữ dạng tự do. Trong phần này, tất cả các chữ "mệnh đề" có
nghĩa tương đương với chữ "câu lệnh".

Các mệnh đề phức hợp
Câu lệnh phức hợp được bọc trong dấu ngoặc { 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
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)
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:
if (<biểu thức>)
<mệnh đề1>
if (<biểu thức>)
<mệnh đề1>
else
<mệnh đề2>
Trần Tiến Hiển-TATA Consultancy Services

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
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ứcX (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 switch thì 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 switch có thể được dùng trong dạng lồng vào nhau (nest), một từ khóa
case hay default sẽ thuộc vào câu lệnh switch bê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> :
Trần Tiến Hiển-TATA Consultancy Services
<mệnh đề M3>
default :
<mệnh đề Mdefault>
}

Các mệnh đề tái lặp (hay vòng lặp)
C có 3 dạng câu lệnh vòng lặp:
Vòng lặp do
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
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
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;
Trần Tiến Hiển-TATA Consultancy Services
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 for sau đâ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
x
x
x

=
=
=
=

10, y = 1
9, y = 3
8, y = 5
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)
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

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

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) {
/* ... */
Trần Tiến Hiển-TATA Consultancy Services
cont: ;
}
break

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

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
Xem thêm bài chínhPhé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 theoC89:
Phép toán

Mô tả

Hướng tiến hành

()

ngoặc đơn (nhóm)

từ trái sang phải

[]
.
->

phần chỉ số của mảng
sự lựa chọn phần tử, nhận dạng
sự lựa chọn phần tử, con trỏ

++

và --

tiền tố tăng/giảm

+và! và ~
(cast)
*
&
sizeof

dấu dương/âm
phép toán Bool NOT/phần bù 0 kiểu bit
đổi kiểu
tham chiếu ngược
tham chiếu
độ lớn

*, /,

nhân/chia/mô dun

từ phải sang trái

+

và %

và -

<<

và >>

cộng/trừ
phép toán bit <ocde>left shift/right shift

<

và <=

quan hệ nhỏ hơn/nhỏ hơn hay bằng

>

và >=

quan hệ lớn hơn/lớn hơn hay bằng

==và !=

bằng với/khác với

từ trái sang phải
Trần Tiến Hiển-TATA Consultancy Services

&

phép toán bit AND

^

phép toán bít XOR

|

phép toán bit OR

&&

phép toán bool AND

||

phép toán bool OR

?:

điều kiện tam phân

=

phép gán giá trị trực tiếp

+= và -=
*=, /=, và %=
<<= và >>=
&=, ^=, va |=

phép gán giá trị cộng thêm/trừ bớt
phép gán giá trị nhân/chia/mô dul bởi
phép gán bit shift
phép gán bit AND/XOR/OR

,

toán tử ,

từ phải sang trái

từ trái sang phải

Nguồn: C Operator Precedence and Associativity

Khai báo dữ liệu
Các kiểu dữ liệu cơ bản
Nhiều ngôn ngữ lập trình kể cả C, biểu thị các số trong hai dạng: nguyên và thực (hay không
nguyên). Sự khác nhau này hình thành từ khía cạnh kỹ thuật của các cách thức xử lý và lưu trữ
các giá trị trong bộ nhớ.
Kiểu nguyên viết dưới dạng 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, long và
2
long long . 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.
Trần Tiến Hiển-TATA Consultancy Services

Đố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
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.
Bản hằng số xác định các biên của những kiểu nguyên thông thường
Đặc tả hiểu ngầm

Đặc tả viết rõ ra

Giá trị nhỏ
nhất

Giá trị lớn
nhất

char

viết y hệt

CHAR_MIN

CHAR_MAX

signed char

viết y hệt

SCHAR_MIN

SCHAR_MAX

unsigned char

viết y hệt

0

UCHAR_MAX

short

signed short int

SHRT_MIN

SHRT_MAX

unsigned short

unsigned short int

0

USHRT_MAX

không viết gì hết, signed, hay

signed int

INT_MIN

INT_MAX

unsigned

unsigned int

0

UINT_MAX

long

signed long int

LONG_MIN

LONG_MAX

unsigned long

unsigned long int

0

ULONG_MAX

int

long long

1

unsigned long long

1

signed long long int
1

unsigned long long
1
int

1

LLONG_MIN

0

— Định tính long long chỉ được hỗ trợ trong các trình dịch thỏa mãn chuẩn C99.

2

LLONG_MAX

2

ULLONG_MAX

2
Trần Tiến Hiển-TATA Consultancy Services
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
Sau đây là danh sách kích cỡ và các biên điển hình của các kiểu nguyên. Các giá trị này có thể
khác nhau tùy theo kiến trúc (máy và trình dịch). ISO C cung cấp tiêu đề inttypes.h, trong đó, có
xác định các kiểu nguyên có dấu và không có dấu nhưng điều chắc chắn là kích cỡ đều nằm
trong khoảng 8 đến 64 bit.
Kích cỡ và biên điển hình của các kiểu nguyên
Đặ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

char

viết y hệt

8

1

-128 or 0

127 hay 255

signed char

viết y hệt

8

1

-128

127

unsigned char

viết y hệt

8

1

0

255

short

signed short int

16

2

-32 768

32 767

unsigned short

unsigned short
int

16

2

0

65 535

long

signed long int

32

4

-2 147 483 648

2 147 483 647

unsigned long

unsigned long
int

32

4

0

4 294 967 295

signed long long
1
int

64

8

-9 223 372 036
854 775 808

9 223 372 036 854
775 807

unsigned long
1
long int

64

8

0

18 446 744 073
709 551 615

long long

1

unsigned long
1
long
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
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
Trần Tiến Hiển-TATA Consultancy Services

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
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
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
Trần Tiến Hiển-TATA Consultancy Services

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ệnh đề cơ bản và tham chiếu tương đương
Đến một giá trị cơ bản Đến một giá trị tham chiếu
Từ một giá trị cơ bản

d

&d

Từ một giá trị tham chiếu

*ptr

ptr

Các mảng
Khai báo mảng tĩnh
Trong C, mảng được dùng để biểu thị một cấu trúc của một dãy nhiều giá trị có cùng một kiểu
được xếp thứ tự. Một mảng gọi là tĩnh nếu độ dài của dãy mảng này cố định. Sự khai báo của
mảng tĩnh có cú pháp sau:
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ử
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
array sẽ 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.
Trần Tiến Hiển-TATA Consultancy Services

Bảng sau đây sẽ minh họa cách dùng của cả hai phương pháp:
Array Chỉ số và con trỏ số học
Phần tử vị trí

0

Kiểu dùng cơ bản array[0]
Dùng con trỏ

*array

1

2

n

array[1]

array[2]

array[n]

*(array + 1) *(array + 2) *(array + n)

Các mảng động
C không cung cấp phương tiện để kiểm tra biên cho các mảng. Nghĩa là nó không thể bắt được
các lỗi khi gán cho một mảng chỉ số âm hay chỉ số vượt quá độ đài của mảng đó. Và hơn thế nữa
các chỉ số trong một mảng có thể vượt khỏi độ dài sẵn có của mảng đó.
Vì các mảng là thuần nhất, tức là nó chỉ chứa các dữ liệu có chung một kiểu nên hai thành phần
thông tin cần nhớ là địa chỉ của phần tử đầu tiên và kiểu của dữ liệu.
Nhắc lại về cú pháp để khai báo một mảng tĩnh, tức là tạo ra một biến tham chiếu nguyên và cấp
phát một vùng nhớ tương ứng cho nó:
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;
Trần Tiến Hiển-TATA Consultancy Services

Các mảng đa chiều
C có hỗ trợ việc dùng mảng đa chiều. Việc định nghĩa chúng giống như là tạo ra mảng của các
mảng , mặc dù vậy trong thực tế nó không hoàn toàn đúng. Cú pháp sau:
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ự
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ự source tiế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 c trong dãy kí tự source và trả
về con trỏ chỉ tới vị trí đó hay con trỏ trống nếu c khô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 a nhỏ
hơn b, 0 nếu chúng bằng nhau, dương nếu a lớn hơn
strcpy(dest, source) - chép và thay các kí tự của dãy source vào dãy dest
strlen(st) - trả về độ dài của st
strncat(dest, source, n) - nối tối đa n kí tự từ dãy source tiếp vào vị trí cuối của
dãy dest; các kí tự sau dấu kết thúc null sẽ không được chép vào
strncmp(a, b, n) - so sánh từ kí tự đầu cho đến tối đa n kí tự từ hai dãy a và b (theo
thứ tự từ điển); hàm trả về số âm nếu phần so sánh của a nhỏ 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 n kí tự từ dãy source vào dãy
dest
strrchr(source, c) - tìm vị trí hiện lần cuối cùng của kí tự c trong dãy source và trả
về một con trỏ chỉ vào vị trí đó hay con trỏ trống nếu không tìm thấy c trong đó

Các hàm ít dùng tới hơn là:
strcoll(s1, s2)
strcspn(s1, s2)
trong s2

- so sánh hai dãy theo một trình tự địa phương đặc thù
- trả về chỉ số của kí tự đầu tiên trong s1 trùng với kí tự bất kì nào
Trần Tiến Hiển-TATA Consultancy Services
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 s1 mà trùng với kí
tự bất kì trong s2 hay 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 s1 mà 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 subst trong dãy
source hay 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 token bên trong s1 mà được phân chia
ra bởi các kí tự trong s2
strxfrm(s1, s2, n) - chuyển đổi s2 thành s1 dùng các quy tắc địa phương đặc thù

Tập tin I/O
Trong C, I/O đưọc tiến hành qua một nhóm các hàm trong thư viện chuẩn. Trong ANSI/ISO C,
những hàm đó được định nghĩa trong stdio.h.
fopen
fclose

Tiêu chuẩn I/O
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 occurredn", stderr);
break;
}
Trần Tiến Hiển-TATA Consultancy Services

/* ... */
putchar(c);
/* ... */
}
return 0;
}

Việc chuyển các đối số qua dòng lệnh
Các tham số được gõ vào một dòng lệnh thì được chuyển vào một chương trình C với hai biến
sẵn có - một để đếm số đối số là 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 ("argct= %in", argc);
for (i = 0; i < argc; i++)
printf ("argv[%i]t= %sn", i, argv[i]);
return 0;
}

Thứ tự đánh giá
Một trình dịch C có thể đánh giá các biểu thức theo thứ tự bất kì giữa dãy các điểm. Dãy các
điểm được định nghĩa bởi:
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
Trần Tiến Hiển-TATA Consultancy Services

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
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 ("%dn", 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.

More Related Content

What's hot

3 Function
3 Function3 Function
3 Function
Cuong
 
Huong danontapc
Huong danontapcHuong danontapc
Huong danontapc
Hồ Lợi
 
1 Gioi Thieu Chung
1 Gioi Thieu Chung1 Gioi Thieu Chung
1 Gioi Thieu Chung
Cuong
 
lap trinh c Phan2 chuong5
 lap trinh c Phan2 chuong5 lap trinh c Phan2 chuong5
lap trinh c Phan2 chuong5
thanhyu
 
Bai tap lap trinh c
Bai tap lap trinh  cBai tap lap trinh  c
Bai tap lap trinh c
tiểu minh
 
Phần 9: Chuỗi ký tự
Phần 9: Chuỗi ký tựPhần 9: Chuỗi ký tự
Phần 9: Chuỗi ký tự
Huy Rùa
 
Giao trinh bai tap c va c++
Giao trinh bai tap c va c++Giao trinh bai tap c va c++
Giao trinh bai tap c va c++
Congdat Le
 

What's hot (18)

Các cấu trúc lệnh trong C
Các cấu trúc lệnh trong CCác cấu trúc lệnh trong C
Các cấu trúc lệnh trong C
 
3 Function
3 Function3 Function
3 Function
 
Giáo trình c++ full tiếng việt
Giáo trình c++ full tiếng việtGiáo trình c++ full tiếng việt
Giáo trình c++ full tiếng việt
 
String c++
String c++String c++
String c++
 
Bài giảng ngôn ngữ lập trình C cơ bản trường đại học công nghiệp thực phẩm TP...
Bài giảng ngôn ngữ lập trình C cơ bản trường đại học công nghiệp thực phẩm TP...Bài giảng ngôn ngữ lập trình C cơ bản trường đại học công nghiệp thực phẩm TP...
Bài giảng ngôn ngữ lập trình C cơ bản trường đại học công nghiệp thực phẩm TP...
 
Huong danontapc
Huong danontapcHuong danontapc
Huong danontapc
 
Sổ tay thư viện hàm ngôn ngữ C
Sổ tay thư viện hàm ngôn ngữ CSổ tay thư viện hàm ngôn ngữ C
Sổ tay thư viện hàm ngôn ngữ C
 
1 Gioi Thieu Chung
1 Gioi Thieu Chung1 Gioi Thieu Chung
1 Gioi Thieu Chung
 
CHUONG_5
CHUONG_5CHUONG_5
CHUONG_5
 
Hàm can bản
Hàm can bảnHàm can bản
Hàm can bản
 
Tin học ứng dụng trong kinh doanh data4u
Tin học ứng dụng trong kinh doanh data4uTin học ứng dụng trong kinh doanh data4u
Tin học ứng dụng trong kinh doanh data4u
 
lap trinh c Phan2 chuong5
 lap trinh c Phan2 chuong5 lap trinh c Phan2 chuong5
lap trinh c Phan2 chuong5
 
Phan2 chuong5 ctrinhcon
Phan2 chuong5 ctrinhconPhan2 chuong5 ctrinhcon
Phan2 chuong5 ctrinhcon
 
Chuong 04 ham
Chuong 04 hamChuong 04 ham
Chuong 04 ham
 
Bai tap lap trinh c
Bai tap lap trinh  cBai tap lap trinh  c
Bai tap lap trinh c
 
Phan2 chuong4 caclenhcautruc
Phan2 chuong4 caclenhcautrucPhan2 chuong4 caclenhcautruc
Phan2 chuong4 caclenhcautruc
 
Phần 9: Chuỗi ký tự
Phần 9: Chuỗi ký tựPhần 9: Chuỗi ký tự
Phần 9: Chuỗi ký tự
 
Giao trinh bai tap c va c++
Giao trinh bai tap c va c++Giao trinh bai tap c va c++
Giao trinh bai tap c va c++
 

Viewers also liked

Nmlt C01 Cac Khai Niem Co Ban Ve Lap Trinh
Nmlt C01 Cac Khai Niem Co Ban Ve Lap TrinhNmlt C01 Cac Khai Niem Co Ban Ve Lap Trinh
Nmlt C01 Cac Khai Niem Co Ban Ve Lap Trinh
Cuong
 
Giao trinh-phan-cung-dien-tu[bookbooming.com]
Giao trinh-phan-cung-dien-tu[bookbooming.com]Giao trinh-phan-cung-dien-tu[bookbooming.com]
Giao trinh-phan-cung-dien-tu[bookbooming.com]
bookbooming1
 
Chapter 1 1 vi
Chapter 1 1 viChapter 1 1 vi
Chapter 1 1 vi
Tan Duy
 
Luan van tot nghiep 2014 - Nguyễn Trọng Hiếu - Athena
Luan van tot nghiep 2014 - Nguyễn Trọng Hiếu - AthenaLuan van tot nghiep 2014 - Nguyễn Trọng Hiếu - Athena
Luan van tot nghiep 2014 - Nguyễn Trọng Hiếu - Athena
Hiếu Nguyễn Trọng
 
Sach tin hoc cb chuan
Sach tin hoc cb chuanSach tin hoc cb chuan
Sach tin hoc cb chuan
Huy Feng
 
Ngon ngu lap trinh c# tieng viet - bach khoaaptech.com
Ngon ngu lap trinh c#   tieng viet - bach khoaaptech.comNgon ngu lap trinh c#   tieng viet - bach khoaaptech.com
Ngon ngu lap trinh c# tieng viet - bach khoaaptech.com
Nguyễn Thành
 

Viewers also liked (20)

Danhsach baitap
Danhsach baitapDanhsach baitap
Danhsach baitap
 
Tổng hợp các gợi ý làm bài tập
Tổng hợp các gợi ý làm bài tậpTổng hợp các gợi ý làm bài tập
Tổng hợp các gợi ý làm bài tập
 
Bai tap c
Bai tap cBai tap c
Bai tap c
 
Kenh sinhvien.net -giao trinh c#
Kenh sinhvien.net -giao trinh c#Kenh sinhvien.net -giao trinh c#
Kenh sinhvien.net -giao trinh c#
 
Nmlt C01 Cac Khai Niem Co Ban Ve Lap Trinh
Nmlt C01 Cac Khai Niem Co Ban Ve Lap TrinhNmlt C01 Cac Khai Niem Co Ban Ve Lap Trinh
Nmlt C01 Cac Khai Niem Co Ban Ve Lap Trinh
 
Phan2 chuong1 gioithieu_c
Phan2 chuong1 gioithieu_cPhan2 chuong1 gioithieu_c
Phan2 chuong1 gioithieu_c
 
Ky thuat lap_trinh
Ky thuat lap_trinhKy thuat lap_trinh
Ky thuat lap_trinh
 
Giao trinh-phan-cung-dien-tu[bookbooming.com]
Giao trinh-phan-cung-dien-tu[bookbooming.com]Giao trinh-phan-cung-dien-tu[bookbooming.com]
Giao trinh-phan-cung-dien-tu[bookbooming.com]
 
Giáo trình C# tieng viet (shared)
Giáo trình C# tieng viet (shared)Giáo trình C# tieng viet (shared)
Giáo trình C# tieng viet (shared)
 
15 Ghép nối 8255
15 Ghép nối 825515 Ghép nối 8255
15 Ghép nối 8255
 
Ky thuat lap trinh c tu co ban den nang cao gs.pham van at - 546 trang
Ky thuat lap trinh c tu co ban den nang cao   gs.pham van at - 546 trangKy thuat lap trinh c tu co ban den nang cao   gs.pham van at - 546 trang
Ky thuat lap trinh c tu co ban den nang cao gs.pham van at - 546 trang
 
Giao Trinh Ngon Ngu Lap Trinh C
Giao Trinh Ngon Ngu Lap Trinh CGiao Trinh Ngon Ngu Lap Trinh C
Giao Trinh Ngon Ngu Lap Trinh C
 
Chapter 1 1 vi
Chapter 1 1 viChapter 1 1 vi
Chapter 1 1 vi
 
Luan van tot nghiep 2014 - Nguyễn Trọng Hiếu - Athena
Luan van tot nghiep 2014 - Nguyễn Trọng Hiếu - AthenaLuan van tot nghiep 2014 - Nguyễn Trọng Hiếu - Athena
Luan van tot nghiep 2014 - Nguyễn Trọng Hiếu - Athena
 
Do hoa may tinh
Do hoa may tinhDo hoa may tinh
Do hoa may tinh
 
Sach tin hoc cb chuan
Sach tin hoc cb chuanSach tin hoc cb chuan
Sach tin hoc cb chuan
 
Ngon ngu lap trinh c# tieng viet - bach khoaaptech.com
Ngon ngu lap trinh c#   tieng viet - bach khoaaptech.comNgon ngu lap trinh c#   tieng viet - bach khoaaptech.com
Ngon ngu lap trinh c# tieng viet - bach khoaaptech.com
 
Lap trinh-c-cho-vdk
Lap trinh-c-cho-vdkLap trinh-c-cho-vdk
Lap trinh-c-cho-vdk
 
Giải hệ phương trình tuyến tính bằng ngôn ngữ lập trình c
Giải hệ phương trình tuyến tính bằng ngôn ngữ lập trình cGiải hệ phương trình tuyến tính bằng ngôn ngữ lập trình c
Giải hệ phương trình tuyến tính bằng ngôn ngữ lập trình c
 
Ngu phap tieng anh
Ngu phap tieng anhNgu phap tieng anh
Ngu phap tieng anh
 

Similar to ưU tiên trong c (20)

Chuong 2
Chuong 2Chuong 2
Chuong 2
 
Ltc 6
Ltc 6Ltc 6
Ltc 6
 
Pointer
PointerPointer
Pointer
 
Lap trinh c_tu_co_ban_den_nang_cao
Lap trinh c_tu_co_ban_den_nang_caoLap trinh c_tu_co_ban_den_nang_cao
Lap trinh c_tu_co_ban_den_nang_cao
 
Lap trinh c_tu_co_ban_den_nang_cao
Lap trinh c_tu_co_ban_den_nang_caoLap trinh c_tu_co_ban_den_nang_cao
Lap trinh c_tu_co_ban_den_nang_cao
 
Chuong 01
Chuong 01Chuong 01
Chuong 01
 
Chuong 01 mo dau
Chuong 01 mo dauChuong 01 mo dau
Chuong 01 mo dau
 
Hàm và nạp chồng hàm
Hàm và nạp chồng hàmHàm và nạp chồng hàm
Hàm và nạp chồng hàm
 
Kế toán Excel
Kế toán ExcelKế toán Excel
Kế toán Excel
 
Chuong 03 lenh
Chuong 03 lenhChuong 03 lenh
Chuong 03 lenh
 
THCS_W11_BaiDocThem
THCS_W11_BaiDocThemTHCS_W11_BaiDocThem
THCS_W11_BaiDocThem
 
Bai giangtrenlop
Bai giangtrenlopBai giangtrenlop
Bai giangtrenlop
 
Nmlt C06 Ham
Nmlt C06 HamNmlt C06 Ham
Nmlt C06 Ham
 
Session 15
Session 15Session 15
Session 15
 
Session 15
Session 15Session 15
Session 15
 
Giotrnhcfulltingvit 131128201133-phpapp02
Giotrnhcfulltingvit 131128201133-phpapp02Giotrnhcfulltingvit 131128201133-phpapp02
Giotrnhcfulltingvit 131128201133-phpapp02
 
Tailieu.vncty.com 06 matlab-osadq3_j2qu_20130412090644_577
Tailieu.vncty.com   06 matlab-osadq3_j2qu_20130412090644_577Tailieu.vncty.com   06 matlab-osadq3_j2qu_20130412090644_577
Tailieu.vncty.com 06 matlab-osadq3_j2qu_20130412090644_577
 
Lesson 2 lý thuyết
Lesson 2 lý thuyếtLesson 2 lý thuyết
Lesson 2 lý thuyết
 
C9 templates
C9 templatesC9 templates
C9 templates
 
C9 templates
C9 templatesC9 templates
C9 templates
 

More from tienhien110293 (6)

Tin hoc dai_cuong_9517
Tin hoc dai_cuong_9517Tin hoc dai_cuong_9517
Tin hoc dai_cuong_9517
 
Tìm hiểu đầy đủ về tràn bộ đệm
Tìm hiểu đầy đủ về tràn bộ đệmTìm hiểu đầy đủ về tràn bộ đệm
Tìm hiểu đầy đủ về tràn bộ đệm
 
Programming technique 1_2_7921
Programming technique 1_2_7921Programming technique 1_2_7921
Programming technique 1_2_7921
 
Mảng 2 chiều
Mảng 2 chiềuMảng 2 chiều
Mảng 2 chiều
 
Lập trình c căn bản
Lập trình c căn bảnLập trình c căn bản
Lập trình c căn bản
 
Tu hoc c_nhanh_nhat_split_1_1055
Tu hoc c_nhanh_nhat_split_1_1055Tu hoc c_nhanh_nhat_split_1_1055
Tu hoc c_nhanh_nhat_split_1_1055
 

Recently uploaded

bài tập lớn môn kiến trúc máy tính và hệ điều hành
bài tập lớn môn kiến trúc máy tính và hệ điều hànhbài tập lớn môn kiến trúc máy tính và hệ điều hành
bài tập lớn môn kiến trúc máy tính và hệ điều hành
dangdinhkien2k4
 
Tử Vi Là Gì Học Luận Giải Tử Vi Và Luận Đoán Vận Hạn
Tử Vi Là Gì Học Luận Giải Tử Vi Và Luận Đoán Vận HạnTử Vi Là Gì Học Luận Giải Tử Vi Và Luận Đoán Vận Hạn
Tử Vi Là Gì Học Luận Giải Tử Vi Và Luận Đoán Vận Hạn
Kabala
 
26 Truyện Ngắn Sơn Nam (Sơn Nam) thuviensach.vn.pdf
26 Truyện Ngắn Sơn Nam (Sơn Nam) thuviensach.vn.pdf26 Truyện Ngắn Sơn Nam (Sơn Nam) thuviensach.vn.pdf
26 Truyện Ngắn Sơn Nam (Sơn Nam) thuviensach.vn.pdf
ltbdieu
 
SD-05_Xây dựng website bán váy Lolita Alice - Phùng Thị Thúy Hiền PH 2 7 8 6 ...
SD-05_Xây dựng website bán váy Lolita Alice - Phùng Thị Thúy Hiền PH 2 7 8 6 ...SD-05_Xây dựng website bán váy Lolita Alice - Phùng Thị Thúy Hiền PH 2 7 8 6 ...
SD-05_Xây dựng website bán váy Lolita Alice - Phùng Thị Thúy Hiền PH 2 7 8 6 ...
ChuThNgnFEFPLHN
 

Recently uploaded (20)

Trắc nghiệm CHƯƠNG 5 môn Chủ nghĩa xã hội
Trắc nghiệm CHƯƠNG 5 môn Chủ nghĩa xã hộiTrắc nghiệm CHƯƠNG 5 môn Chủ nghĩa xã hội
Trắc nghiệm CHƯƠNG 5 môn Chủ nghĩa xã hội
 
các nội dung phòng chống xâm hại tình dục ở trẻ em
các nội dung phòng chống xâm hại tình dục ở trẻ emcác nội dung phòng chống xâm hại tình dục ở trẻ em
các nội dung phòng chống xâm hại tình dục ở trẻ em
 
ĐỀ KIỂM TRA CUỐI KÌ 2 BIÊN SOẠN THEO ĐỊNH HƯỚNG ĐỀ BGD 2025 MÔN TOÁN 10 - CÁN...
ĐỀ KIỂM TRA CUỐI KÌ 2 BIÊN SOẠN THEO ĐỊNH HƯỚNG ĐỀ BGD 2025 MÔN TOÁN 10 - CÁN...ĐỀ KIỂM TRA CUỐI KÌ 2 BIÊN SOẠN THEO ĐỊNH HƯỚNG ĐỀ BGD 2025 MÔN TOÁN 10 - CÁN...
ĐỀ KIỂM TRA CUỐI KÌ 2 BIÊN SOẠN THEO ĐỊNH HƯỚNG ĐỀ BGD 2025 MÔN TOÁN 10 - CÁN...
 
[123doc] - ao-dai-truyen-thong-viet-nam-va-xuong-xam-trung-quoc-trong-nen-van...
[123doc] - ao-dai-truyen-thong-viet-nam-va-xuong-xam-trung-quoc-trong-nen-van...[123doc] - ao-dai-truyen-thong-viet-nam-va-xuong-xam-trung-quoc-trong-nen-van...
[123doc] - ao-dai-truyen-thong-viet-nam-va-xuong-xam-trung-quoc-trong-nen-van...
 
Giáo trình xây dựng thực đơn. Ths Hoang Ngoc Hien.pdf
Giáo trình xây dựng thực đơn. Ths Hoang Ngoc Hien.pdfGiáo trình xây dựng thực đơn. Ths Hoang Ngoc Hien.pdf
Giáo trình xây dựng thực đơn. Ths Hoang Ngoc Hien.pdf
 
Đề thi tin học HK2 lớp 3 Chân Trời Sáng Tạo
Đề thi tin học HK2 lớp 3 Chân Trời Sáng TạoĐề thi tin học HK2 lớp 3 Chân Trời Sáng Tạo
Đề thi tin học HK2 lớp 3 Chân Trời Sáng Tạo
 
20 ĐỀ DỰ ĐOÁN - PHÁT TRIỂN ĐỀ MINH HỌA BGD KỲ THI TỐT NGHIỆP THPT NĂM 2024 MÔ...
20 ĐỀ DỰ ĐOÁN - PHÁT TRIỂN ĐỀ MINH HỌA BGD KỲ THI TỐT NGHIỆP THPT NĂM 2024 MÔ...20 ĐỀ DỰ ĐOÁN - PHÁT TRIỂN ĐỀ MINH HỌA BGD KỲ THI TỐT NGHIỆP THPT NĂM 2024 MÔ...
20 ĐỀ DỰ ĐOÁN - PHÁT TRIỂN ĐỀ MINH HỌA BGD KỲ THI TỐT NGHIỆP THPT NĂM 2024 MÔ...
 
bài tập lớn môn kiến trúc máy tính và hệ điều hành
bài tập lớn môn kiến trúc máy tính và hệ điều hànhbài tập lớn môn kiến trúc máy tính và hệ điều hành
bài tập lớn môn kiến trúc máy tính và hệ điều hành
 
Tử Vi Là Gì Học Luận Giải Tử Vi Và Luận Đoán Vận Hạn
Tử Vi Là Gì Học Luận Giải Tử Vi Và Luận Đoán Vận HạnTử Vi Là Gì Học Luận Giải Tử Vi Và Luận Đoán Vận Hạn
Tử Vi Là Gì Học Luận Giải Tử Vi Và Luận Đoán Vận Hạn
 
26 Truyện Ngắn Sơn Nam (Sơn Nam) thuviensach.vn.pdf
26 Truyện Ngắn Sơn Nam (Sơn Nam) thuviensach.vn.pdf26 Truyện Ngắn Sơn Nam (Sơn Nam) thuviensach.vn.pdf
26 Truyện Ngắn Sơn Nam (Sơn Nam) thuviensach.vn.pdf
 
Bài học phòng cháy chữa cháy - PCCC tại tòa nhà
Bài học phòng cháy chữa cháy - PCCC tại tòa nhàBài học phòng cháy chữa cháy - PCCC tại tòa nhà
Bài học phòng cháy chữa cháy - PCCC tại tòa nhà
 
Giới Thiệu Về Kabala | Hành Trình Thấu Hiểu Bản Thân | Kabala.vn
Giới Thiệu Về Kabala | Hành Trình Thấu Hiểu Bản Thân | Kabala.vnGiới Thiệu Về Kabala | Hành Trình Thấu Hiểu Bản Thân | Kabala.vn
Giới Thiệu Về Kabala | Hành Trình Thấu Hiểu Bản Thân | Kabala.vn
 
Luận văn 2024 Thực trạng và giải pháp nâng cao hiệu quả công tác quản lý hành...
Luận văn 2024 Thực trạng và giải pháp nâng cao hiệu quả công tác quản lý hành...Luận văn 2024 Thực trạng và giải pháp nâng cao hiệu quả công tác quản lý hành...
Luận văn 2024 Thực trạng và giải pháp nâng cao hiệu quả công tác quản lý hành...
 
22 ĐỀ THI THỬ TUYỂN SINH TIẾNG ANH VÀO 10 SỞ GD – ĐT THÁI BÌNH NĂM HỌC 2023-2...
22 ĐỀ THI THỬ TUYỂN SINH TIẾNG ANH VÀO 10 SỞ GD – ĐT THÁI BÌNH NĂM HỌC 2023-2...22 ĐỀ THI THỬ TUYỂN SINH TIẾNG ANH VÀO 10 SỞ GD – ĐT THÁI BÌNH NĂM HỌC 2023-2...
22 ĐỀ THI THỬ TUYỂN SINH TIẾNG ANH VÀO 10 SỞ GD – ĐT THÁI BÌNH NĂM HỌC 2023-2...
 
30 ĐỀ PHÁT TRIỂN THEO CẤU TRÚC ĐỀ MINH HỌA BGD NGÀY 22-3-2024 KỲ THI TỐT NGHI...
30 ĐỀ PHÁT TRIỂN THEO CẤU TRÚC ĐỀ MINH HỌA BGD NGÀY 22-3-2024 KỲ THI TỐT NGHI...30 ĐỀ PHÁT TRIỂN THEO CẤU TRÚC ĐỀ MINH HỌA BGD NGÀY 22-3-2024 KỲ THI TỐT NGHI...
30 ĐỀ PHÁT TRIỂN THEO CẤU TRÚC ĐỀ MINH HỌA BGD NGÀY 22-3-2024 KỲ THI TỐT NGHI...
 
60 CÂU HỎI ÔN TẬP LÝ LUẬN CHÍNH TRỊ NĂM 2024.docx
60 CÂU HỎI ÔN TẬP LÝ LUẬN CHÍNH TRỊ NĂM 2024.docx60 CÂU HỎI ÔN TẬP LÝ LUẬN CHÍNH TRỊ NĂM 2024.docx
60 CÂU HỎI ÔN TẬP LÝ LUẬN CHÍNH TRỊ NĂM 2024.docx
 
Giáo trình nhập môn lập trình - Đặng Bình Phương
Giáo trình nhập môn lập trình - Đặng Bình PhươngGiáo trình nhập môn lập trình - Đặng Bình Phương
Giáo trình nhập môn lập trình - Đặng Bình Phương
 
Chương 6: Dân tộc - Chủ nghĩa xã hội khoa học
Chương 6: Dân tộc - Chủ nghĩa xã hội khoa họcChương 6: Dân tộc - Chủ nghĩa xã hội khoa học
Chương 6: Dân tộc - Chủ nghĩa xã hội khoa học
 
Xem sim phong thủy luận Hung - Cát số điện thoại chính xác nhất.pdf
Xem sim phong thủy luận Hung - Cát số điện thoại chính xác nhất.pdfXem sim phong thủy luận Hung - Cát số điện thoại chính xác nhất.pdf
Xem sim phong thủy luận Hung - Cát số điện thoại chính xác nhất.pdf
 
SD-05_Xây dựng website bán váy Lolita Alice - Phùng Thị Thúy Hiền PH 2 7 8 6 ...
SD-05_Xây dựng website bán váy Lolita Alice - Phùng Thị Thúy Hiền PH 2 7 8 6 ...SD-05_Xây dựng website bán váy Lolita Alice - Phùng Thị Thúy Hiền PH 2 7 8 6 ...
SD-05_Xây dựng website bán váy Lolita Alice - Phùng Thị Thúy Hiền PH 2 7 8 6 ...
 

ưU tiên trong c

  • 1. Trần Tiến Hiển-TATA Consultancy Services CÚ PHÁP NGÔN NGỮ 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 Cú pháp 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ụ 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>; stdio.h int add(int x, int y) { return x + y; //Chú giải: dòng này khai báo tập tin bao gồm là
  • 2. Trần Tiến Hiển-TATA Consultancy Services } 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 <code>return</code> hoàn toàn có thể dùng các câu lệnh khác đơn giản hơn. */ } int main(void) { int z = 1; int y = -2; printf("%d + 1 = %dn", z, add(z, 1)); printf ("absolute value of %d is %d", y, abs(y)); return 0; } Chú ý: phần mã trên đã được thử thành công dùng trình dịch GNU (cho ANSI C và C99) Mô tả Trong các câu lệnh tiền xử lý, ở cấp độ cao nhất, một chương trình ngôn ngữ C luôn có một chuỗi các khai báo cho các tập tin bao gồm. Sau đó là các khai báo của phạm vi tập tin. Các khai báo này giới thiệu các hàm, các biến và các kiểu biến. Các hàm trong C nhìn tương tự với các chương trình con của Fortran hay các thủ tục của Pascal. Định nghĩa của hàm xuất hiện trong phần thân của nó (phần giữa bộ dấu ngoặc { 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ư
  • 3. Trần Tiến Hiển-TATA Consultancy Services 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 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 <code>main<code> 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)); *p = n; } // đăng kí một vùng nhớ // 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; } 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. int **p
  • 4. Trần Tiến Hiển-TATA Consultancy Services 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 Một cách cơ bản thì C là ngôn ngữ dạng tự do. Trong phần này, tất cả các chữ "mệnh đề" có nghĩa tương đương với chữ "câu lệnh". Các mệnh đề phức hợp Câu lệnh phức hợp được bọc trong dấu ngoặc { 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 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) 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: if (<biểu thức>) <mệnh đề1> if (<biểu thức>) <mệnh đề1> else <mệnh đề2>
  • 5. Trần Tiến Hiển-TATA Consultancy Services 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 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ứcX (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 switch thì 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 switch có thể được dùng trong dạng lồng vào nhau (nest), một từ khóa case hay default sẽ thuộc vào câu lệnh switch bê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> :
  • 6. Trần Tiến Hiển-TATA Consultancy Services <mệnh đề M3> default : <mệnh đề Mdefault> } Các mệnh đề tái lặp (hay vòng lặp) C có 3 dạng câu lệnh vòng lặp: Vòng lặp do 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 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 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;
  • 7. Trần Tiến Hiển-TATA Consultancy Services 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 for sau đâ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 x x x = = = = 10, y = 1 9, y = 3 8, y = 5 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) 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 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 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) { /* ... */
  • 8. Trần Tiến Hiển-TATA Consultancy Services cont: ; } break 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 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 Xem thêm bài chínhPhé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 theoC89: Phép toán Mô tả Hướng tiến hành () ngoặc đơn (nhóm) từ trái sang phải [] . -> phần chỉ số của mảng sự lựa chọn phần tử, nhận dạng sự lựa chọn phần tử, con trỏ ++ và -- tiền tố tăng/giảm +và! và ~ (cast) * & sizeof dấu dương/âm phép toán Bool NOT/phần bù 0 kiểu bit đổi kiểu tham chiếu ngược tham chiếu độ lớn *, /, nhân/chia/mô dun từ phải sang trái + và % và - << và >> cộng/trừ phép toán bit <ocde>left shift/right shift < và <= quan hệ nhỏ hơn/nhỏ hơn hay bằng > và >= quan hệ lớn hơn/lớn hơn hay bằng ==và != bằng với/khác với từ trái sang phải
  • 9. Trần Tiến Hiển-TATA Consultancy Services & phép toán bit AND ^ phép toán bít XOR | phép toán bit OR && phép toán bool AND || phép toán bool OR ?: điều kiện tam phân = phép gán giá trị trực tiếp += và -= *=, /=, và %= <<= và >>= &=, ^=, va |= phép gán giá trị cộng thêm/trừ bớt phép gán giá trị nhân/chia/mô dul bởi phép gán bit shift phép gán bit AND/XOR/OR , toán tử , từ phải sang trái từ trái sang phải Nguồn: C Operator Precedence and Associativity Khai báo dữ liệu Các kiểu dữ liệu cơ bản Nhiều ngôn ngữ lập trình kể cả C, biểu thị các số trong hai dạng: nguyên và thực (hay không nguyên). Sự khác nhau này hình thành từ khía cạnh kỹ thuật của các cách thức xử lý và lưu trữ các giá trị trong bộ nhớ. Kiểu nguyên viết dưới dạng 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, long và 2 long long . 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.
  • 10. Trần Tiến Hiển-TATA Consultancy Services Đố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 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. Bản hằng số xác định các biên của những kiểu nguyên thông thường Đặc tả hiểu ngầm Đặc tả viết rõ ra Giá trị nhỏ nhất Giá trị lớn nhất char viết y hệt CHAR_MIN CHAR_MAX signed char viết y hệt SCHAR_MIN SCHAR_MAX unsigned char viết y hệt 0 UCHAR_MAX short signed short int SHRT_MIN SHRT_MAX unsigned short unsigned short int 0 USHRT_MAX không viết gì hết, signed, hay signed int INT_MIN INT_MAX unsigned unsigned int 0 UINT_MAX long signed long int LONG_MIN LONG_MAX unsigned long unsigned long int 0 ULONG_MAX int long long 1 unsigned long long 1 signed long long int 1 unsigned long long 1 int 1 LLONG_MIN 0 — Định tính long long chỉ được hỗ trợ trong các trình dịch thỏa mãn chuẩn C99. 2 LLONG_MAX 2 ULLONG_MAX 2
  • 11. Trần Tiến Hiển-TATA Consultancy Services 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 Sau đây là danh sách kích cỡ và các biên điển hình của các kiểu nguyên. Các giá trị này có thể khác nhau tùy theo kiến trúc (máy và trình dịch). ISO C cung cấp tiêu đề inttypes.h, trong đó, có xác định các kiểu nguyên có dấu và không có dấu nhưng điều chắc chắn là kích cỡ đều nằm trong khoảng 8 đến 64 bit. Kích cỡ và biên điển hình của các kiểu nguyên Đặ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 char viết y hệt 8 1 -128 or 0 127 hay 255 signed char viết y hệt 8 1 -128 127 unsigned char viết y hệt 8 1 0 255 short signed short int 16 2 -32 768 32 767 unsigned short unsigned short int 16 2 0 65 535 long signed long int 32 4 -2 147 483 648 2 147 483 647 unsigned long unsigned long int 32 4 0 4 294 967 295 signed long long 1 int 64 8 -9 223 372 036 854 775 808 9 223 372 036 854 775 807 unsigned long 1 long int 64 8 0 18 446 744 073 709 551 615 long long 1 unsigned long 1 long 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 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
  • 12. Trần Tiến Hiển-TATA Consultancy Services 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 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 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
  • 13. Trần Tiến Hiển-TATA Consultancy Services 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ệnh đề cơ bản và tham chiếu tương đương Đến một giá trị cơ bản Đến một giá trị tham chiếu Từ một giá trị cơ bản d &d Từ một giá trị tham chiếu *ptr ptr Các mảng Khai báo mảng tĩnh Trong C, mảng được dùng để biểu thị một cấu trúc của một dãy nhiều giá trị có cùng một kiểu được xếp thứ tự. Một mảng gọi là tĩnh nếu độ dài của dãy mảng này cố định. Sự khai báo của mảng tĩnh có cú pháp sau: 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ử 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 array sẽ 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.
  • 14. Trần Tiến Hiển-TATA Consultancy Services Bảng sau đây sẽ minh họa cách dùng của cả hai phương pháp: Array Chỉ số và con trỏ số học Phần tử vị trí 0 Kiểu dùng cơ bản array[0] Dùng con trỏ *array 1 2 n array[1] array[2] array[n] *(array + 1) *(array + 2) *(array + n) Các mảng động C không cung cấp phương tiện để kiểm tra biên cho các mảng. Nghĩa là nó không thể bắt được các lỗi khi gán cho một mảng chỉ số âm hay chỉ số vượt quá độ đài của mảng đó. Và hơn thế nữa các chỉ số trong một mảng có thể vượt khỏi độ dài sẵn có của mảng đó. Vì các mảng là thuần nhất, tức là nó chỉ chứa các dữ liệu có chung một kiểu nên hai thành phần thông tin cần nhớ là địa chỉ của phần tử đầu tiên và kiểu của dữ liệu. Nhắc lại về cú pháp để khai báo một mảng tĩnh, tức là tạo ra một biến tham chiếu nguyên và cấp phát một vùng nhớ tương ứng cho nó: 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;
  • 15. Trần Tiến Hiển-TATA Consultancy Services Các mảng đa chiều C có hỗ trợ việc dùng mảng đa chiều. Việc định nghĩa chúng giống như là tạo ra mảng của các mảng , mặc dù vậy trong thực tế nó không hoàn toàn đúng. Cú pháp sau: 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ự 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ự source tiế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 c trong dãy kí tự source và trả về con trỏ chỉ tới vị trí đó hay con trỏ trống nếu c khô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 a nhỏ hơn b, 0 nếu chúng bằng nhau, dương nếu a lớn hơn strcpy(dest, source) - chép và thay các kí tự của dãy source vào dãy dest strlen(st) - trả về độ dài của st strncat(dest, source, n) - nối tối đa n kí tự từ dãy source tiếp vào vị trí cuối của dãy dest; các kí tự sau dấu kết thúc null sẽ không được chép vào strncmp(a, b, n) - so sánh từ kí tự đầu cho đến tối đa n kí tự từ hai dãy a và b (theo thứ tự từ điển); hàm trả về số âm nếu phần so sánh của a nhỏ 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 n kí tự từ dãy source vào dãy dest strrchr(source, c) - tìm vị trí hiện lần cuối cùng của kí tự c trong dãy source và trả về một con trỏ chỉ vào vị trí đó hay con trỏ trống nếu không tìm thấy c trong đó Các hàm ít dùng tới hơn là: strcoll(s1, s2) strcspn(s1, s2) trong s2 - so sánh hai dãy theo một trình tự địa phương đặc thù - trả về chỉ số của kí tự đầu tiên trong s1 trùng với kí tự bất kì nào
  • 16. Trần Tiến Hiển-TATA Consultancy Services 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 s1 mà trùng với kí tự bất kì trong s2 hay 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 s1 mà 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 subst trong dãy source hay 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 token bên trong s1 mà được phân chia ra bởi các kí tự trong s2 strxfrm(s1, s2, n) - chuyển đổi s2 thành s1 dùng các quy tắc địa phương đặc thù Tập tin I/O Trong C, I/O đưọc tiến hành qua một nhóm các hàm trong thư viện chuẩn. Trong ANSI/ISO C, những hàm đó được định nghĩa trong stdio.h. fopen fclose Tiêu chuẩn I/O 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 occurredn", stderr); break; }
  • 17. Trần Tiến Hiển-TATA Consultancy Services /* ... */ putchar(c); /* ... */ } return 0; } Việc chuyển các đối số qua dòng lệnh Các tham số được gõ vào một dòng lệnh thì được chuyển vào một chương trình C với hai biến sẵn có - một để đếm số đối số là 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 ("argct= %in", argc); for (i = 0; i < argc; i++) printf ("argv[%i]t= %sn", i, argv[i]); return 0; } Thứ tự đánh giá Một trình dịch C có thể đánh giá các biểu thức theo thứ tự bất kì giữa dãy các điểm. Dãy các điểm được định nghĩa bởi: 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
  • 18. Trần Tiến Hiển-TATA Consultancy Services 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 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 ("%dn", 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.