text:
Kiểu và khai báo biến trong C
Ngôn ngữ lập trình C có một hệ thống mở rộng cho việc khai báo các biến của các kiểu khác nhau. Những quy tắc dành cho các kiểu phức tạp có thể gây nhầm lẫn tùy theo các kiểu thiết kế của chúng. Bài này nói về các khai báo biến, bắt đầu từ các kiểu đơn giản, và dẫn tới các kiểu phức tạp hơn.
Kiểu cơ bản[sửa | sửa mã nguồn]
Có 4 kiểu cơ bản của các biến trong C; đó là:
char,
int,
double và
float.
Để khai báo một biến có kiểu cơ bản, tên của kiểu được ghi ra trước sau đó đến tên của biến mới (hay của nhiều biến mới cách phân cách nhau bởi dấu phẩy) -- (Xem thêm định nghĩa dãy điểm)
char red; int blue, yellow;
Các định tính khác nhau có thể đặt vào trong các kiểu cơ bản này để điều chỉnh kích cỡ và sẽ được miêu tả trong phần sau.
Lưu ý: Ở đây chỉ nêu ra trường hợp khai báo đơn giản không đi kèm với việc gán giá trị khởi động cho biến
Dấu[sửa | sửa mã nguồn]
Một kiểu được gọi là có dấu nếu kiểu nguyên đó có thể chứa các số âm. Ngược lại các kiểu cơ bản nào không chấp nhận các số âm là kiểu không dấu.
Có hai kiểu nguyên là
char và
int có thể có dấu âm hay không. Theo mặc định thì mọi kiểu
int là có dấu (nghĩa là chúng chấp nhận các số âm). Để dùng dưới dạng không có dấu (tức là kiểu nguyên chỉ chấp nhận các sô không âm) thì từ khoá
unsigned phải được dùng. Ngoài ra, thay vì khai báo đầy đủ trong dạng
unsigned int, người ta có thể lược bỏ bớt từ khóa
int (và nó được xem như hiểu ngầm—điều này chỉ dùng được cho kiểu
int mà thôi). Như vậy hai khai báo sau đây hoàn toàn tương đương:
unsigned int green; unsigned green;
Đặc tả của C không xác định rõ ràng là kiểu
char sẽ là loại có dấu hay không dấu; khi đó, dấu của kiểu này tùy thuộc vào quy định của nhà phát hành trình dịch. Như vậy, một cách để giảm sai sót khi làm việc trên nhiều loại trình dịch C khác nhau là khai báo rõ ràng bằng các định tính
signed hay
unsigned nếu dùng kiểu
char để tính toán trên các con số. (Dầu sao, nó thực sự sẽ không quá quan trọng nếu dùng kiểu
char như là kiểu "ký tự".)
unsigned char grey; signed char white;
Tiêu chuẩn chung yêu cầu
char,
signed char,
unsigned char là các kiểu khác nhau. Ngoài ra, các hàm chuẩn về dãy các kí tự sử dụng các con trỏ chỉ tới kiểu
char (không có định tính), nhiều trình dịch C sẽ bắt lỗi (hay cảnh cáo) nếu các kiểu kí tự khác được dùng như là dãy kí tự được chuyển vào các hàm này.
Kích cỡ[sửa | sửa mã nguồn]
- Trong phần này hai cụm từ "chiếm" và "có độ dài" đều có nghĩa là "phần bộ nhớ cần thiết để dành cho một biến"; biến này có kiểu được miêu tả tùy theo chi tiết của bài viết.
Kiểu
int cũng có các định tính về kích cỡ để đặc biệt hóa tầm rộng của giá trị mà kiểu này cho phép (tương ứng với đó là việc thay đổi phần bộ nhớ dùng để chứa các số có kiểu này).
short int yellow; long int orange;
Tương tự như đã đề cập trong phần trước, người ta có thể bỏ không viết từ khóa
int trong các kiểu mà đầy đủ phải viết là
short int or
long int. Thí dụ hai khai báo sau đây là tương đương.
long int brown; long brown;
Có một số nhầm lẫn trong giới hiểu biết về C như là các kiểu nguyên có độ lớn bao nhiêu. Trong tiêu chuẩn thì không chỉ một cách rõ ràng việc này:
- Kiểu
short intkhông thể lớn hơn kiểu
int.
- Kiểu
intkhông thể lớn hơn
long int.
- Kiểu
short intphải dài ít nhất 16 bit.
- Kiểu
long intphải dài ít nhất 32 bit.
Trong tiêu chuẩn đã không đòi hỏi gì về các kích cỡ nêu trên và những khác nhau cần thiết. (Nghĩa là hoàn toàn hợp lệ nếu cả ba kiểu đều dài 64 bit!) Để có được một miêu tả chính xác và đơn giản của các kiểu, một máy tính người ta áp dụng vào trong mỗi kiểu (cũng như là kích cỡ của một kiểu con trỏ; xem phần đưới đây) một loại lược đồ đã được tạo ra; (xem:64-Bit Programming Models). Hai lược đồ được biết nhiều nhất là
-
ILP32, trong đó
int,
long intvà các kiểu con trỏ chiếm 32 bit.
LP64, trong đó,
long intvà con trỏ mỗi loại chiếm 64 bit, còn
intcó độ dài 32 bit.
-
Hầu hết các trình dịch dùng các lược đồ trên dùng 16 bit cho kiểu
short int.
Một biến
double có thể là một
long double, mà trình dịch có thể sử dụng thay cho một kiểu
double thuần túy. Tương tự tình huống trước, chuẩn C không hề nêu rõ các kích cỡ tương đối giữa các giá trị dấu chấm động, mà chỉ đòi hỏi
float không được lớn hơn
long double về kích cỡ.
Từ khóa định tính
const cho các kiểu[sửa | sửa mã nguồn]
Để giúp tăng cường độ an toàn trong các chương trình, các giá trị có thể được đánh dấu là các hằng bằng từ khóa định tính
const. Với từ khóa này thì một biến khai báo trở thành một hằng. Mọi thao tác do vô ý hay cố ý để điều chỉnh giá trị của nó sẽ bị báo lỗi bởi hầu hết các trình dịch. Bởi vì sau khi đã dùng từ khóa định tính
const thì các giá trị của biến không thể thay đổi nữa nên người lập trình phải gán giá trị ban đầu ngay lúc khai báo.
Chuẩn C cho phép hoán đổi vị trí của các hiệu chính. Thí dụ cả hai khai báo hằng sau đây là tương đương
int const black = 12; const int black = 12;
Cách khai báo đầu thường phản ánh cách dùng
const trong cách dùng kiểu con trỏ trong khi cách thứ nhì lại tự nhiên hơn và phổ dụng hơn.
Con trỏ[sửa | sửa mã nguồn]
Một biến có thể được khai báo như là một con trỏ chỉ đến các giá trị có kiểu nào đó, với ý nghĩa của dùng từ khóa định tính *. Để khai báo chỉ việc viết thêm ngay trước tên biến một dấu sao:
char *square; long *circle;
Lưu ý: Nếu dùng nhiều hơn một dấu sao thì sẽ tạo nên dạng các con trỏ đứng trước chỉ vào con trỏ đứng sau và con trỏ cuối cùng mới chỉ đến địa chỉ của giá trị biến.
Trong cuốn "The C Programming Language" (Ngôn ngữ lập trình C) có cho một giải thích tường tận về việc "hơi kì cục" khi dùng dấu sao trước tên của biến, trong khi dường như việc dùng dấu sao này đứng trước tên của kiểu thì có vẻ "hợp lý" hơn. Đó chính là việc tham chiếu ngược con trỏ, nó có kiểu của đối tượng mà nó chỉ tới. Trong thí dụ trên,
*circle là một giá trị của kiểu
long. Trong khi điều này khó thấy rõ trong thí dụ trên, thì nó lại cho thấy ưu điểm nếu dùng trong các kiểu phức hợp. Đây là lí do tại sao C "hơi kì cục" trong cách khai báo các kiểu phức hợp, lúc đó, tên của biến sẽ không còn rõ ràng trong khi khai báo kiểu như các thí dụ sẽ nêu trong phần tiếp sau đây.
Có một kiểu đặc biệt của giá trị mà không thể dùng được trực tiếp như là biến có kiểu, nhưng lại có thể chỉ đến nó nếu khai báo con trỏ.
void *triangle;
Giá trị được chỉ tới ở đây không thể dùng trực tiếp được; mọi cố gắng để tham chiếu ngược con trỏ này sẽ dẫn tới một lỗi. Sự tiện lợi ở đây là vì nó là một con trỏ "tổng quát"; nó hữu dụng khi làm việc trên dữ liệu mà kiểu được chỉ tới là không giữ vai trò gì quan trọng. Đơn giản chỉ cần cái địa chỉ con trỏ. Nó thường được ứng dụng để chứa các con trỏ trong các kiểu để làm tiện ích như là danh sách liên kết, bảng băm (hash). Khi nào cần thì tiện ích sẽ đổi kiểu (typecast) thành con trỏ có kiểu cần dùng.
Sau đây là thí dụ về các khai báo con trỏ hợp lệ:
long int *rectangle; unsigned short int *rhombus; const char *kite;
Lưu ý đặc biệt về việc dùng
const trong trường hợp cuối cùng: ở đây
kite là một con trỏ không phải là hằng chỉ tới một
const char (tức là nó chỉ tới là một hằng có kiểu kí tự). Giá trị của
kite tự nó không phải là hằng, chỉ có giá trị của
char mà nó chỉ tới là một hằng.
Vị trí của từ khoá
const đặt sau kiểu sẽ cho một cách thức để khai báo hằng con trỏ. Và như là một hằng, nó phải được gán giá trị khởi động khi khai báo:
char * const pentagon = &some_char;
Ở đây,
pentagon là một hằng con trỏ, mà nó chỉ tới một
char. Giá trị mà nó chỉ tới lại không là một hằng; và sẽ không gây lỗi khi thay đổi kí tự được nó chỉ tới. Chỉ khi nào thay đổi chính con trỏ này thì sẽ gây lỗi (vì đã khai báo nó là hằng). Cũng có thể khai báo cả hai: con trỏ và giá trị mà nó chỉ tới đều là hằng. Có hai cách tương đương nếu muốn khai báo như vậy là:
char const * const hexagon = &some_char; const char * const hexagon = &some_char;
Con trỏ chỉ tới con trỏ[sửa | sửa mã nguồn]
Vì lý do một khai báo chẳng hạn như
char * tự nó là một kiểu, nên một biến con trỏ có thể được khai báo để nó chỉ vào các giá trị có kiểu như vây. Nói gọn hơn, chúng là con trỏ chỉ tới các con trỏ. Thí dụ:
char **septagon;
Như đã đề cập phần trên các từ khóa định tính
const có thể áp dụng vào chẳng hạn:
unsigned long const int * const *octogon;
Dòng trên khai báo
octogon là một con trỏ chỉ tới một hằng con trỏ, và hằng con trỏ này trở lại chỉ tới một hằng số nguyên dạng
unsigned long. Các kiểu con trỏ có thể lồng nhau, nhưng chúng càng trở nên khó khăn để nghĩ tới việc sử dụng khi mà càng nhiều cấp độ của sự gián tiếp tham gia vào. Mọi mã dùng nhiều hơn hai cấp độ của con trỏ có thể sẽ cần tới một sự thiết kế, dạng
struct các con trỏ.
Mảng[sửa | sửa mã nguồn]
Đối với nhiều người lập trình, trong hầu hết các ngôn ngữ tương tự C, kiểu của một mảng nằm trong số phần tử mà nó chứa. Do vậy, khai báo sau đây có thể dùng trong các ngôn ngữ như Java hay C# để khai báo một mảng 10 giá trị số nguyên.
int[10] cat; /* THIS IS NOT VALID C CODE */
Mặc dù vậy, như đã nhắc tới trước đây, nguyên lý trong cú pháp khai báo của C làm cho việc khai báo tương tự như việc sử dụng của biến. Thí dụ: một truy cập tới mảng này chẳng hạn như là
cat[i], lúc khai khai báo lại cũng có cú pháp dạng:
int cat[10];
Mảng của các mảng[sửa | sửa mã nguồn]
Tương tự như con trỏ, kiểu mảng có thể được lồng nhau. Vì trong cách viết mảng sử dụng các ngoặc vuông (
[]), là một cách viết hậu tố, nên kích cỡ của mảng bên trong thì được ghi ở bên ngoài (hay đằng sau):
double dog[5][12];
Câu lệnh trên khai báo rằng
dog là một mảng có năm phần tử. Mỗi phần tử là một mảng của 12 giá trị
double.
Mảng của các con trỏ[sửa | sửa mã nguồn]
Vì kiểu của phần trong một mảng tự nó lại là một kiểu của C, mảng của các con trỏ đương nhiên cũng có cấu trúc:
char *mice[10];
Câu lệnh này khai báo biến
mice là mảng của 10 phần tử, trong đó, mỗi phần tử là một con trỏ chỉ tới
char.
Con trỏ chỉ tới các mảng[sửa | sửa mã nguồn]
Để khai báo một biến là một con trỏ chỉ tới một mảng, nhất thiết phải dùng tới dấu ngoặc đơn. Nó tương tự như cách dùng ngoặc để đổi thứ tự ưu tiên cho phép toán (phép toán trong ngoặc sẽ được tính trước) chẳng hạn:
2 + 3 * 4 (2 + 3) * 4
Hoàn toàn tương tự cho con trỏ chỉ tới các mảng. Lưu ý rằng dấu ngoặc vuông (
[]) có độ ưu tiên cao hơn dấu sao (
*), do đó khai báo sẽ có dạng:
double (*elephant)[20];
Câu lệnh này khai báo biến
elephant là một con trỏ, và nó chỉ tới một mảng có 20 giá trị kiểu
double.
Để khai báo một con trỏ chỉ tới dãy các con trỏ, chỉ cần kết hợp các cách viết:
int *(*crocodile)[15];
Hàm[sửa | sửa mã nguồn]
Một sự khai báo hàm là một thí dụ điển hình của một kiểu dẫn xuất. Bởi vì hàm có thể nhận vào các tham số, kiểu của mỗi tham số phải được ghi rõ ra. Tên của mỗi tham số không nhất thiết phải được cho trước khi khai báo một hàm. Hai cách khai báo sau đây là tương đương:
long bat(char); long bat(char c);
Tham số[sửa | sửa mã nguồn]
Trong khi cả hai dạng trên đều đúng cú pháp, thì cách viết bỏ qua tên của các tham số thường được xét như là một dạng tồi khi viết các khai báo hàm trong các tập tin tiêu đề. Các tên này có thể cung ứng các thông tin có giá trị cho những người đọc các tập tin đó chẳng hạn như là ý nghĩa và phép toán của chúng.
Các hàm có thể nhận và trả về các kiểu con trỏ dùng cách viết thông thường cho một con trỏ:
int const *ball(long int l, int i, unsigned char *s);
Kiểu đặc biệt
void hữu dụng cho việc khai báo các hàm mà chúng không có tham số nào cả:
char *wicket(void);
Điều này khác với một bộ tham số trống rỗng, được dùng trong ANSI C, để khai báo một hàm, nhưng không cho bất cứ thông tin nào về các kiểu tham số của nó.
double umpire();
Câu lệnh trên khai báo một hàm tên là
umpire, nó trả về một giá trị
double, nhưng không đề cập gì về các tham số mà hàm đó dùng tới.
Hàm nhận hàm khác làm tham số[sửa | sửa mã nguồn]
Trong C, các hàm không thể trực tiếp lấy các hàm khác như là tham số của nó, hay không thể trả về một hàm số như là kết quả. Mặc dù vậy, chúng có thể lấy vào hay trả về các con trỏ. Để khai báo rằng một hàm lấy một con trỏ hàm như là một tham số, thì dùng cách viết chuẩn như đã ghi ở trên.
int crowd(char p1, int (*p2)(void));
Khai báo bên trên có một hàm mà có hai tham số. Đối số đầu tiên,
p1, là một kí tự kiểu
char thông thường. Đối số còn lại,
p2 là một con trỏ chỉ tới một hàm. Hàm được chỉ tới này không (nên) có các tham số, và sẽ trả về một số nguyên
int.
Hàm trả về một hàm khác[sửa | sửa mã nguồn]
Để khai báo một hàm mà nó trả về một hàm khác phải dùng tới dấu ngoặc đơn, để thay thứ tự ưu tiên của các phép toán (về hàm)
long (*boundary(int height, int width))(int x, int y);
Như trên, có hai bộ danh sách tham số, sự khai báo này nên được đọc thật kĩ, vì nó không được rõ ràng. Ở đây, hàm
boundary được định nghĩa. Nó có hai tham số nguyên
height và
width, và trả về một con trỏ hàm. Con trỏ trả về này chỉ tới một hàm mà tự hàm đó có hai tham số nguyên là
x và
y, và trả về một số nguyên
long.
Cách này có thể được mở rộng tùy ý để làm cho các hàm trả về con trỏ chỉ tới hàm mà hàm đó lại trả về các con trỏ, mà các con trỏ này chỉ tới các hàm khác, và vân vân, nhưng việc này sẽ biến mã nguồn trở nên khó hiểu một cách nhanh chóng, và rất dễ phát sinh lỗi. Nếu thấy cần thiết làm chuyện đó, thì người lập trình nên cứu xét việc thiết kế lại hay dùng một cách định nghĩa kiểu
typedef.
Cấu trúc[sửa | sửa mã nguồn]
Cấu trúc (từ khóa tương ứng
struct) thực sự là một "kiểu mở rộng" của mảng. So với mảng thì cấu trúc mạnh hơn ở chỗ nó cho phép các phần tử của nó có các kiểu khác nhau và mỗi phần tử này được gọi là thành phần của một cấu trúc:
struct person { char name[60]; int age; }; //lưu ý dấu ";" cần dùng để kết thúc câu lệnh
Câu lệnh
struct nêu trên là một khai báo chuẩn để tạo ra một kiểu cấu trúc trong C.
Định nghĩa biến kiểu
struct[sửa | sửa mã nguồn]
Việc định nghĩa một biến có kiểu
struct cũng đơn giản như khi định nghĩa các biến bình thường:
struct person Bluesman; struct person Bio = { "Hieu", 30 };
Trong cách đầu thì biến Bluesman chưa có giá trị khởi động (nó vẫn có thể được truy cập và thay đổi giá trị sau này) trong khi biến Bio đã được gán các giá trị ban đầu. Hãy lưu ý dùng dấu phẩy "
," để phân biệt các giá trị được gán lên những thành phần của cấu trúc—và dĩ nhiên chúng phải có đúng kiểu cũng như không thể gán thiếu các giá trị cho các thành phần này.
Để truy cập đến các giá trị của biến có kiểu struct thì có thể dùng toán tử "." như câu lệnh sau:
printf("Name: %s\n", Bio.name);
Mảng của các
struct[sửa | sửa mã nguồn]
Để kiến tạo một mảng của các
struct thì dùng cú pháp sau:
struct person list[10];
Con trỏ chỉ tới
struct[sửa | sửa mã nguồn]
Cũng vậy, việc tiến hành khai báo một biến con trỏ có kiểu là
struct tương tự cách thông thường. Chỉ cần thêm vào đó dấu sao đằng trước tên biến:
struct person *Huong;
Cấu trúc lồng nhau[sửa | sửa mã nguồn]
Kiểu cấu trúc cũng có thể định nghĩa lồng vào nhau. Thí dụ dưới đây cho thấy việc khai báo cấu trúc
worker có chứa cấu trúc
person như là một thành phần. Việc truy cập dữ liệu thành phần của cấu trúc bên trong cũng được tiến hành theo cách dùng toán tử "." nối tiếp nhau.
struct person { char name[60]; int age; }; struct worker { struct person peronal_ID; char job[30]; float income; };
Kiểu hợp nhất[sửa | sửa mã nguồn]
Kiểu hợp nhất có tên từ khóa là
union kiểu đặc biệt này cho phép nó chứa dữ liệu mà có thể có kiểu khác nhau trong cùng một phần bộ nhớ (mà nó có thể được cấp phát khi khai báo biến):
union folder { int number; double real; char letter; }; //lưu ý dấu ";" cần dùng để kết thúc câu lệnh
Để khai báo biến, có thể dùng cách thông thường, tạo mảng các
union hay cách tham chiếu:
union folder matter; union folder listtype[100]; union folder *matterptr;
Để gán hay truy cập giá trị cho một biến union, có thể dùng toán tử "." Theo hàng khai báo đầu tiên của thí dụ trên ta có thể viết một trong các phép gán:
matter.real=3.1416;
hay là:
matter.letter = 't';
hay là:
matter.number = 1;
Lưu ý:
- Việc gán giá trị cho một biến kiểu
unionđòi hỏi kiểu của dữ liệu đó phải có mặt trong khai báo ban đầu của nó. Theo thí dụ trên thì kiểu
folderchỉ chấp nhận chứa một đơn vị dữ liệu của một trong ba kiểu
int, double,và
char.
- Một khi giá trị có kiểu đúng nào đó được gán cho một biến kiểu
unionthì nó sẽ xóa bỏ hẳn giá trị cũ (nếu có) mà biến này đã chứa trước đó.
- Việc truy cập một giá trị từ một biến kiểu
unioncần lưu ý đến kiểu hiện tại của dữ liệu đang được chứa của biến này nếu không, có thể gây ra lỗi dùng sai kiểu.
- Điểm khác nhau quan trọng giữa
unionvà
structlà
unionchỉ có được một thành phần (nhưng thành phần này phải có kiểu tùy theo khai báo của người lập trình) trong khi
structbao gồm nhiều thành phần (và mỗi thành phần có thể có kiểu khác nhau).
- Tương tự như
strruct,
unioncho phép khai báo nhiều union lồng nhau.
Dùng
#define để định nghĩa hằng và kiểu[sửa | sửa mã nguồn]
Một cách tổng quát thì từ khóa tiền xử lý
#define đùng để định nghĩa tên của một kiểu (đối tượng) nào đó. Thực ra, câu lệnh
#define chỉ là một loại câu lệnh macro. Có hai ứng dụng chính như sau:
Định nghĩa tên hằng[sửa | sửa mã nguồn]
Có thể dùng câu lệnh tiền xử lý
#define để định nghĩa một hằng:
#define PI 3.14159 //định nghĩa tên một hằng số PI #define STANDARD "ANSI C" //định nghĩa tên một hằng dãy kí tự #define ESC '\033' //định nghĩa tên một hằng kí tự mã ASCII của phím Esc.
Lưu ý: so với cách định nghĩa dùng từ khóa
const thì cách dùng này không được uyển chuyển bằng nhưng nó thường cho hiệu quả thực thi nhanh hơn vì đây chỉ là các macro.
Định nghĩa tên của kiểu dữ liệu[sửa | sửa mã nguồn]
Có thể dùng
#define để định nghĩa tên của một kiểu dữ liệu:
#define real float //định nghĩa tên kiẻu real cho dữ liệu có kiểu float
Việc khai báo các biến không có gì khác lạ ngoại trừ tên mới được dùng:
real x, y[3], *z;
Lưu ý: Việc sử dụng
#define có thể có các hiệu ứng phụ không ngờ nếu dùng nó kết hợp với nhiều định tính và có thể dẫn đến những lỗi khó tìm khi viết mã:
#define STRING char *
Trong lúc định nghĩa biến người lập có thể muốn định nghĩa hai con trỏ
char như sau:
STRING name, job;
Tuy nhiên, điều ước muốn sẽ không xảy ra vì
#define là macro nên trình dịch sẽ diễn giải thành (nó chỉ thay thế tên
STRING bằng
char *):
char * name, job;
Và như vậy, người lập trình sẽ không nhận được hai biến con trỏ như dự tính mà chỉ có một biến
name là con trỏ mà thôi.
Dùng
typedef để định nghĩa kiểu[sửa | sửa mã nguồn]
Một cách khác để đặt tên riêng cho kiểu dữ liệu là dùng câu lệnh với từ khóa
typedef:
typedef float real;
Nếu so sánh cách viết trong thí dụ trên với việc dùng từ khoá
#define để định nghĩa thì chúng hoàn toàn tương đương (chỉ khác nhau về thứ tự các chữ
float và
real). Tuy nhiên, cách viết này là một sự thay thế thế tên "đúng nghĩa" chứ không phải là một macro đơn thuần. Trở lại thí dụ:
typedef char* string;
Câu lệnh trên cho phép đặt tên string như là một kiểu mới (mà nội dung của nó là kiểu con trỏ
char). Bây giờ hãy xét đến câu lệnh khai báo biến:
string name, job;
Trường hợp này sẽ được trình dịch diễn dịch đúng theo mong muốn thành:
char *name, *job;
Dùng cho
struct[sửa | sửa mã nguồn]
Một thí dụ khác liên quan đến việc đặt tên cho
struct là việc kết hợp cả hai khai báo và đặt tên lại trong cùng một câu lệnh:
typedef struct { char * name; int * age; } person;
Như vậy khi khai báo biến chỉ cần viết là:
person Trung;
Ứng dụng[sửa | sửa mã nguồn]
Một ứng dụng đáng lưu ý của
typedef là việc làm cho mã C trở nên linh hoạt hơn trong nhiều môi trường khác nhau. Thí dụ: khi muốn xác định dùng đúng 4 byte cho một kiểu nguyên nhưng trên một số hệ máy thì nó ứng với kiểu
int, trong khi trên một số hệ máy khác nó lại ứng với kiểu
long int. Để giải quyết việc dùng chính xác 4 byte cho kiểu nguyên mà người lập trình muốn, thì có thể dùng giải pháp là: thêm vào một tập tin bao gồm trong đó có chứa định nghĩa:
typedef int FOURBYTE; //dùng cho các máy lấy
intlà 4 byte
hay định nghĩa:
typedef long int FOURBYTE; //dùng cho các máy lấy
long intlà 4 byte
và chỉ cần thêm vào trong mã nguồn câu lệnh
#include <Tên_tập_tin_bao_gồm> như vậy chỉ cần thay nội dung của tập tin bao gồm thì toàn bộ mã vẫn hoạt động đúng.
Kiểu
enum[sửa | sửa mã nguồn]
Kiểu
enum là một kiểu dữ liệu đặc biệt được dùng để định nghĩa một quan hệ thứ tự cho một tập họp hữu hạn các tên. (Trong thực tế thì
enum có kiểu là
int—Theo trang 553 trong cuốn "New C Primer Plus"—xem thêm phần tham khảo):
enum Wiki {Arisa, Bluesman, VietBio, Trung, Quang, Minh};
Để khai báo biến
member có kiểu
enum dùng câu lệnh:
enum member;
Các giá trị (hiểu ngầm) của các kí hiệu
Arisa, Bluesman, VietBio, Trung, Quang, Minh theo mặc định sẽ tương ứng với 0, 1, 2, 3, 4, 5. Các câu lệnh cách viết sau đây là có hiệu lực:
member = Minh; if (member == VietBio) { do_some_commands } for (member=Arisa; member <= Trung; member++) { do_some_commands }
Như vậy, theo mặc định, các tên của một
enum được xem là các hằng số từ 0 tăng dần cho đến tên cuối cùng.
Tuy nhiên, C không loại trừ khả năng xếp lại giá trị của một kiểu
enum theo cách riêng:
enum reordert={duck,cat=10, mouse =50, elephant =1000, lion, virus};
Trong thí dụ trên thì
duck có giá trị tương ứng là 0,
cat là 10,...,
elephant là 1000, còn
lion tương ứng với giá trị 1001 và
virus tương ứng với 1002.
Một trong những ứng dụng chính của kiểu này là để tăng cường khả năng đọc mã được dễ hiểu hay phù hợp hơn.
Kiểu
FILE[sửa | sửa mã nguồn]
Kiểu
FILE là kiểu dữ liệu dùng để xử lí các tập tin. Theo ANSI thì có hai phương thức để truy cập là nhị phân (binary) và văn bản (text). Người ta dùng một biến con trỏ để khai báo:
FILE *fp;
Thủ tục quan trọng cần làm tiếp theo là việc mở tập tin. Hàm thường được dùng để mở tập tin là
fopen
fp = fopen ("Dung.txt", "r");
Trong dòng lệnh trên thì tập tin có tên
Dung.txt sẽ được mở trong chế độ đọc
r. Các chế độ truy cập cơ bản bao gồm:
r(đọc)
w(viết)
a(viết tiếp vào cuối tập tin và tạo tập tin mới nếu chưa có tập tin này)
r+(đọc và viết)
w+(đọc và viết nhưng cắt bỏ nội dung cũ của tập tin nếu có, tạo tập tin nếu nó chưa tồn tại)
a+
- Các chế độ
rb, wb, ab, rb+, r+b, wb+, w+b, ab+, a+bgiống như các trường hợp trên nhưng chỉ dùng cho tập tin nhị phân.
Để tiếp tục việc xử lí thì có thể dùng tới các hàm trong thư viện chuẩn như:
getc(), putc(), fprintf(), fscanf(), fgets(), fputs(), fseek(), ftell() và hàm
fclose().
Lưu ý về biến được khai báo
static[sửa | sửa mã nguồn]
Các biến có được xác định bởi định tính
static đặt trước tên kiểu biến khi khai báo sẽ cho biến đó một tính năng đặc biệt, đó là, giá trị của nó sẽ được lưu giữ không bị mất đi mặc dù khối mã chứa nó đã được xử lí xong. Trường hợp. Đặc biệt nếu một biến được khai báo có định tính
static trong một hàm và được cài đặt giá trị nào đó thì sau khi hàm đó được gọi, giá trị của biến
static đó vẫn còn giữ nguyên giữa mỗi lần gọi (cho tới khi nó được gán giá trị khác trong lần gọi tới của hàm). Thi dụ sau đây khai báo biến my_static có định tính
static trong một hàm:
#include<stdio.h> int static_func(int init) { static int my_static_var; my_static_var += init; return my_static_var; } int main(void) { printf("call the 1st time (init=0), my_static_var = %d\n", static_func(0)); printf("call the 2nd time (init=1), my_static_var = %d\n", static_func(1)); printf("call the 3rd time (init=2), my_static_var = %d\n", static_func(2)); }
Sau khi dịch và chạy mã này sẽ cho kết quả:
call the 1st time (init=0), my_static_var = 0 //0 +0 =0 call the 2nd time (init=1), my_static_var = 1 //0 +1 =1 call the 3rd time (init=2), my_static_var = 3 //1 +2 =3
Lưu ý: Mọi biến toàn cục đều có định tính
static một cách tự động.
Xem thêm[sửa | sửa mã nguồn]
Tham Khảo[sửa | sửa mã nguồn]
- New C Primer Plus. The Waite Group's. SAM Publishing. 1993. ISBN 0-672-30319-1

markdown:
# Kiểu và khai báo biến trong C
|Bài viết này
|cần thêm .
|
|
## Mục lục
[Ngôn ngữ lập trình C](/wiki/C_(ng%C3%B4n_ng%E1%BB%AF_l%E1%BA%ADp_tr%C3%ACnh)) có một hệ thống mở rộng cho việc **khai báo các biến của các kiểu khác nhau**. Những quy tắc dành cho các kiểu phức tạp có thể gây nhầm lẫn tùy theo các kiểu thiết kế của chúng. Bài này nói về các khai báo biến, bắt đầu từ các kiểu đơn giản, và dẫn tới các kiểu phức tạp hơn.
## Kiểu cơ bản[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=1) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=1)]
Có 4 kiểu cơ bản của các biến trong C; đó là:
char,
int,
double và
float.
|Tên kiểu||Ý nghĩa|
|
||Đơn vị cơ bản nhất có thể địa chỉ hóa được; nó là một byte. Đây là một kiểu nguyên.|
|
||Loại số nguyên theo kích cỡ tự nhiên nhất của các máy tính. Thông thường nó có thể lấy trọn một khoảng có thể địa chỉ hoá được của một
|
|
||Một giá trị dấu chấm động có độ chính xác đơn.|
|
||Một giá trị dấu chấm động có độ chính xác kép.|
Để khai báo một biến có kiểu cơ bản, tên của kiểu được ghi ra trước sau đó đến tên của biến mới (hay của nhiều biến mới cách phân cách nhau bởi dấu phẩy) -- (Xem thêm định nghĩa
[dãy điểm](/wiki/C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C#Th.E1.BB.A9_t.E1.BB.B1_.C4.91.C3.A1nh_gi.C3.A1))
char red; int blue, yellow;
Các
[định tính](/wiki/C%C3%BA_ph%C3%A1p_ng%C3%B4n_ng%E1%BB%AF_C#QUALIFIER) khác nhau có thể đặt vào trong các kiểu cơ bản này để điều chỉnh kích cỡ và sẽ được miêu tả trong phần sau. Lưu ý: Ở đây chỉ nêu ra trường hợp khai báo đơn giản không đi kèm với việc gán giá trị khởi động cho biến
### Dấu[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=2) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=2)]
Một kiểu được gọi là
**có dấu** nếu kiểu nguyên đó có thể chứa các số âm. Ngược lại các kiểu cơ bản nào không chấp nhận các số âm là kiểu **không dấu**.
Có hai kiểu nguyên là
char và
int có thể có dấu âm hay không. Theo mặc định thì mọi kiểu
int là có dấu (nghĩa là chúng chấp nhận các số âm). Để dùng dưới dạng không có dấu (tức là kiểu nguyên chỉ chấp nhận các sô không âm) thì từ khoá
unsigned phải được dùng. Ngoài ra, thay vì khai báo đầy đủ trong dạng
unsigned int, người ta có thể lược bỏ bớt từ khóa
int (và nó được xem như hiểu ngầm—điều này chỉ dùng được cho kiểu
int mà thôi). Như vậy hai khai báo sau đây hoàn toàn tương đương:
unsigned int green; unsigned green;
Đặc tả của C không xác định rõ ràng là kiểu
char sẽ là loại có dấu hay không dấu; khi đó, dấu của kiểu này tùy thuộc vào quy định của nhà phát hành trình dịch. Như vậy, một cách để giảm sai sót khi làm việc trên nhiều loại trình dịch C khác nhau là khai báo rõ ràng bằng các định tính
signed hay
unsigned nếu dùng kiểu
char để tính toán trên các con số. (Dầu sao, nó thực sự sẽ không quá quan trọng nếu dùng kiểu
char như là kiểu "ký tự".)
unsigned char grey; signed char white;
Tiêu chuẩn chung yêu cầu
char,
signed char,
unsigned char là các kiểu khác nhau. Ngoài ra, các hàm chuẩn về dãy các kí tự sử dụng các con trỏ chỉ tới kiểu
char (không có định tính), nhiều trình dịch C sẽ bắt lỗi (hay cảnh cáo) nếu các kiểu kí tự khác được dùng như là dãy kí tự được chuyển vào các hàm này.
### Kích cỡ[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=3) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=3)] *Trong phần này hai cụm từ "chiếm" và "có độ dài" đều có nghĩa là "phần bộ nhớ cần thiết để dành cho một biến"; biến này có kiểu được miêu tả tùy theo chi tiết của bài viết*.
Kiểu
int cũng có các định tính về kích cỡ để đặc biệt hóa tầm rộng của giá trị mà kiểu này cho phép (tương ứng với đó là việc thay đổi phần bộ nhớ dùng để chứa các số có kiểu này).
short int yellow; long int orange;
Tương tự như đã đề cập trong phần trước, người ta có thể bỏ không viết từ khóa
int trong các kiểu mà đầy đủ phải viết là
short int or
long int. Thí dụ hai khai báo sau đây là tương đương.
long int brown; long brown;
Có một số nhầm lẫn trong giới hiểu biết về C như là các kiểu nguyên có độ lớn bao nhiêu. Trong tiêu chuẩn thì không chỉ một cách rõ ràng việc này:
- Kiểu
short intkhông thể lớn hơn kiểu
int.
- Kiểu
intkhông thể lớn hơn
long int.
- Kiểu
short intphải dài ít nhất 16 bit.
- Kiểu
long intphải dài ít nhất 32 bit.
Trong tiêu chuẩn đã không đòi hỏi gì về các kích cỡ nêu trên và những khác nhau cần thiết. (Nghĩa là hoàn toàn hợp lệ nếu cả ba kiểu đều dài 64 bit!) Để có được một miêu tả chính xác và đơn giản của các kiểu, một
[máy tính](/wiki/M%C3%A1y_t%C3%ADnh) người ta áp dụng vào trong mỗi kiểu (cũng như là kích cỡ của một kiểu con trỏ; xem phần đưới đây) một loại lược đồ đã được tạo ra; (xem: [64-Bit Programming Models](http://www.opengroup.org/public/tech/aspen/lp64_wp.htm)). Hai lược đồ được biết nhiều nhất là
-
ILP32, trong đó
int,
long intvà các kiểu con trỏ chiếm 32 bit.
LP64, trong đó,
long intvà con trỏ mỗi loại chiếm 64 bit, còn
intcó độ dài 32 bit.
-
Hầu hết các trình dịch dùng các lược đồ trên dùng 16 bit cho kiểu
short int.
Một biến
double có thể là một
long double, mà trình dịch có thể sử dụng thay cho một kiểu
double thuần túy. Tương tự tình huống trước, chuẩn C không hề nêu rõ các kích cỡ tương đối giữa các giá trị dấu chấm động, mà chỉ đòi hỏi
float không được lớn hơn
long double về kích cỡ.
### Từ khóa định tính
const cho các kiểu[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=4) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=4)]
Để giúp tăng cường độ an toàn trong các chương trình, các giá trị có thể được đánh dấu là các hằng bằng từ khóa định tính
const. Với từ khóa này thì một biến khai báo trở thành một hằng. Mọi thao tác do vô ý hay cố ý để điều chỉnh giá trị của nó sẽ bị báo lỗi bởi hầu hết các trình dịch. Bởi vì sau khi đã dùng từ khóa định tính
const thì các giá trị của biến không thể thay đổi nữa nên người lập trình phải gán giá trị ban đầu ngay lúc khai báo.
Chuẩn C cho phép hoán đổi vị trí của các hiệu chính. Thí dụ cả hai khai báo hằng sau đây là tương đương
int const black = 12; const int black = 12;
Cách khai báo đầu thường phản ánh cách dùng
const trong cách dùng kiểu con trỏ trong khi cách thứ nhì lại tự nhiên hơn và phổ dụng hơn.
## Con trỏ[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=5) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=5)]
Một biến có thể được khai báo như là một con trỏ chỉ đến các giá trị có kiểu nào đó, với ý nghĩa của dùng từ khóa định tính
***. Để khai báo chỉ việc viết thêm ngay trước tên biến một dấu sao:
char *square; long *circle;
Lưu ý: Nếu dùng nhiều hơn một dấu sao thì sẽ tạo nên dạng các con trỏ đứng trước chỉ vào con trỏ đứng sau và con trỏ cuối cùng mới chỉ đến địa chỉ của giá trị biến.
Trong cuốn "
*The C Programming Language*" (Ngôn ngữ lập trình C) có cho một giải thích tường tận về việc "hơi kì cục" khi dùng dấu sao trước tên của biến, trong khi dường như việc dùng dấu sao này đứng trước tên của kiểu thì có vẻ "hợp lý" hơn. Đó chính là việc [tham chiếu ngược](/w/index.php?title=Tham_chi%E1%BA%BFu_ng%C6%B0%E1%BB%A3c&action=edit&redlink=1) con trỏ, nó có kiểu của đối tượng mà nó chỉ tới. Trong thí dụ trên,
*circle là một
*giá trị* của kiểu
long. Trong khi điều này khó thấy rõ trong thí dụ trên, thì nó lại cho thấy ưu điểm nếu dùng trong các kiểu phức hợp. Đây là lí do tại sao C "hơi kì cục" trong cách khai báo các kiểu phức hợp, lúc đó, tên của biến sẽ không còn rõ ràng trong khi khai báo kiểu như các thí dụ sẽ nêu trong phần tiếp sau đây.
Có một kiểu đặc biệt của giá trị mà không thể dùng được trực tiếp như là biến có kiểu, nhưng lại có thể chỉ đến nó nếu khai báo con trỏ.
void *triangle;
Giá trị được chỉ tới ở đây không thể dùng trực tiếp được; mọi cố gắng để
[tham chiếu ngược](/w/index.php?title=Tham_chi%E1%BA%BFu_ng%C6%B0%E1%BB%A3c&action=edit&redlink=1) con trỏ này sẽ dẫn tới một lỗi. Sự tiện lợi ở đây là vì nó là một con trỏ "tổng quát"; nó hữu dụng khi làm việc trên dữ liệu mà kiểu được chỉ tới là không giữ vai trò gì quan trọng. Đơn giản chỉ cần cái địa chỉ con trỏ. Nó thường được ứng dụng để chứa các con trỏ trong các kiểu để làm tiện ích như là [danh sách liên kết](/w/index.php?title=Danh_s%C3%A1ch_li%C3%AAn_k%E1%BA%BFt&action=edit&redlink=1), bảng băm ( *hash*). Khi nào cần thì tiện ích sẽ [đổi kiểu](/w/index.php?title=%C4%90%E1%BB%95i_ki%E1%BB%83u&action=edit&redlink=1) ( *typecast*) thành con trỏ có kiểu cần dùng.
Sau đây là thí dụ về các khai báo con trỏ hợp lệ:
long int *rectangle; unsigned short int *rhombus; const char *kite;
Lưu ý đặc biệt về việc dùng
const trong trường hợp cuối cùng: ở đây
kite là một con trỏ không phải là hằng chỉ tới một
const char (tức là nó chỉ tới là một hằng có kiểu kí tự). Giá trị của
kite tự nó không phải là hằng, chỉ có giá trị của
char mà nó chỉ tới là một hằng.
Vị trí của từ khoá
const đặt sau kiểu sẽ cho một cách thức để khai báo hằng con trỏ. Và như là một hằng, nó phải được gán giá trị khởi động khi khai báo:
char * const pentagon = &some_char;
Ở đây,
pentagon là một hằng con trỏ, mà nó chỉ tới một
char. Giá trị mà nó chỉ tới lại không là một hằng; và sẽ không gây lỗi khi thay đổi kí tự được nó chỉ tới. Chỉ khi nào thay đổi chính con trỏ này thì sẽ gây lỗi (vì đã khai báo nó là hằng). Cũng có thể khai báo cả hai: con trỏ và giá trị mà nó chỉ tới đều là hằng. Có hai cách tương đương nếu muốn khai báo như vậy là:
char const * const hexagon = &some_char; const char * const hexagon = &some_char;
### Con trỏ chỉ tới con trỏ[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=6) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=6)]
Vì lý do một khai báo chẳng hạn như
char * tự nó là một kiểu, nên một biến con trỏ có thể được khai báo để nó chỉ vào các giá trị có kiểu như vây. Nói gọn hơn, chúng là con trỏ chỉ tới các con trỏ. Thí dụ:
char **septagon;
Như đã đề cập phần trên các từ khóa định tính
const có thể áp dụng vào chẳng hạn:
unsigned long const int * const *octogon;
Dòng trên khai báo
octogon là một con trỏ chỉ tới một hằng con trỏ, và hằng con trỏ này trở lại chỉ tới một hằng số nguyên dạng
unsigned long. Các kiểu con trỏ có thể lồng nhau, nhưng chúng càng trở nên khó khăn để nghĩ tới việc sử dụng khi mà càng nhiều cấp độ của sự gián tiếp tham gia vào. Mọi mã dùng nhiều hơn hai cấp độ của con trỏ có thể sẽ cần tới một sự thiết kế, dạng
struct các con trỏ.
## Mảng[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=7) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=7)]
Đối với nhiều người lập trình, trong hầu hết các ngôn ngữ tương tự C, kiểu của một mảng nằm trong số phần tử mà nó chứa. Do vậy, khai báo sau đây có thể dùng trong các ngôn ngữ như
[Java](/wiki/Java_(ng%C3%B4n_ng%E1%BB%AF_l%E1%BA%ADp_tr%C3%ACnh)) hay [C#](/wiki/C_th%C4%83ng) để khai báo một mảng 10 giá trị số nguyên.
int[10] cat; /* THIS IS NOT VALID C CODE */
Mặc dù vậy, như đã nhắc tới trước đây, nguyên lý trong cú pháp khai báo của C làm cho việc khai báo tương tự như việc sử dụng của biến. Thí dụ: một truy cập tới mảng này chẳng hạn như là
cat[i], lúc khai khai báo lại cũng có cú pháp dạng:
int cat[10];
### Mảng của các mảng[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=8) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=8)]
Tương tự như con trỏ, kiểu mảng có thể được lồng nhau. Vì trong cách viết mảng sử dụng các ngoặc vuông (
[]), là một cách viết hậu tố, nên kích cỡ của mảng bên trong thì được ghi ở bên ngoài (hay đằng sau):
double dog[5][12];
Câu lệnh trên khai báo rằng
dog là một mảng có năm phần tử. Mỗi phần tử là một mảng của 12 giá trị
double.
### Mảng của các con trỏ[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=9) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=9)]
Vì kiểu của phần trong một mảng tự nó lại là một kiểu của C, mảng của các con trỏ đương nhiên cũng có cấu trúc:
char *mice[10];
Câu lệnh này khai báo biến
mice là mảng của 10 phần tử, trong đó, mỗi phần tử là một con trỏ chỉ tới
char.
### Con trỏ chỉ tới các mảng[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=10) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=10)]
Để khai báo một biến là một con trỏ chỉ tới một mảng, nhất thiết phải dùng tới dấu ngoặc đơn. Nó tương tự như cách dùng ngoặc để đổi thứ tự ưu tiên cho phép toán (phép toán trong ngoặc sẽ được tính trước) chẳng hạn:
2 + 3 * 4 (2 + 3) * 4
Hoàn toàn tương tự cho con trỏ chỉ tới các mảng. Lưu ý rằng dấu ngoặc vuông (
[]) có độ ưu tiên cao hơn dấu sao (
*), do đó khai báo sẽ có dạng:
double (*elephant)[20];
Câu lệnh này khai báo biến
elephant là một con trỏ, và nó chỉ tới một mảng có 20 giá trị kiểu
double.
Để khai báo một con trỏ chỉ tới dãy các con trỏ, chỉ cần kết hợp các cách viết:
int *(*crocodile)[15];
## Hàm[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=11) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=11)]
Một sự khai báo hàm là một thí dụ điển hình của một
[kiểu dẫn xuất](/w/index.php?title=Ki%E1%BB%83u_d%E1%BA%ABn_xu%E1%BA%A5t&action=edit&redlink=1). Bởi vì hàm có thể nhận vào các tham số, kiểu của mỗi tham số phải được ghi rõ ra. Tên của mỗi tham số không nhất thiết phải được cho trước khi khai báo một hàm. Hai cách khai báo sau đây là tương đương:
long bat(char); long bat(char c);
### Tham số[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=12) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=12)]
Trong khi cả hai dạng trên đều đúng cú pháp, thì cách viết bỏ qua tên của các tham số thường được xét như là một dạng tồi khi viết các khai báo hàm trong các
[tập tin tiêu đề](/w/index.php?title=T%E1%BA%ADp_tin_ti%C3%AAu_%C4%91%E1%BB%81&action=edit&redlink=1). Các tên này có thể cung ứng các thông tin có giá trị cho những người đọc các tập tin đó chẳng hạn như là ý nghĩa và phép toán của chúng.
Các hàm có thể nhận và trả về các kiểu con trỏ dùng cách viết thông thường cho một con trỏ:
int const *ball(long int l, int i, unsigned char *s);
Kiểu đặc biệt
void hữu dụng cho việc khai báo các hàm mà chúng không có tham số nào cả:
char *wicket(void);
Điều này khác với một bộ tham số trống rỗng, được dùng trong ANSI C, để khai báo một hàm, nhưng không cho bất cứ thông tin nào về các kiểu tham số của nó.
double umpire();
Câu lệnh trên khai báo một hàm tên là
umpire, nó trả về một giá trị
double, nhưng không đề cập gì về các tham số mà hàm đó dùng tới.
### Hàm nhận hàm khác làm tham số[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=13) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=13)]
Trong C, các hàm không thể trực tiếp lấy các hàm khác như là tham số của nó, hay không thể trả về một hàm số như là kết quả. Mặc dù vậy, chúng có thể lấy vào hay trả về các con trỏ. Để khai báo rằng một hàm lấy một con trỏ hàm như là một tham số, thì dùng cách viết chuẩn như đã ghi ở trên.
int crowd(char p1, int (*p2)(void));
Khai báo bên trên có một hàm mà có hai tham số. Đối số đầu tiên,
p1, là một kí tự kiểu
char thông thường. Đối số còn lại,
p2 là một con trỏ chỉ tới một hàm. Hàm được chỉ tới này không (nên) có các tham số, và sẽ trả về một số nguyên
int.
### Hàm trả về một hàm khác[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=14) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=14)]
Để khai báo một hàm mà nó trả về một hàm khác phải dùng tới dấu ngoặc đơn, để thay thứ tự ưu tiên của các phép toán (về hàm)
long (*boundary(int height, int width))(int x, int y);
Như trên, có hai bộ danh sách tham số, sự khai báo này nên được đọc thật kĩ, vì nó không được rõ ràng. Ở đây, hàm
boundary được định nghĩa. Nó có hai tham số nguyên
height và
width, và trả về một con trỏ hàm. Con trỏ trả về này chỉ tới một hàm mà tự hàm đó có hai tham số nguyên là
x và
y, và trả về một số nguyên
long.
Cách này có thể được mở rộng tùy ý để làm cho các hàm trả về con trỏ chỉ tới hàm mà hàm đó lại trả về các con trỏ, mà các con trỏ này chỉ tới các hàm khác, và vân vân, nhưng việc này sẽ biến mã nguồn trở nên khó hiểu một cách nhanh chóng, và rất dễ phát sinh lỗi. Nếu thấy cần thiết làm chuyện đó, thì người lập trình nên cứu xét việc thiết kế lại hay dùng một cách định nghĩa kiểu
typedef.
## Cấu trúc[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=15) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=15)]
Cấu trúc (từ khóa tương ứng
struct) thực sự là một "kiểu mở rộng" của mảng. So với mảng thì cấu trúc mạnh hơn ở chỗ nó cho phép các phần tử của nó có các kiểu khác nhau và mỗi phần tử này được gọi là
**thành phần** của một cấu trúc:
struct person { char name[60]; int age; }; //lưu ý dấu ";" cần dùng để kết thúc câu lệnh
Câu lệnh
struct nêu trên là một khai báo chuẩn để tạo ra một kiểu cấu trúc trong C.
### Định nghĩa biến kiểu
struct[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=16) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=16)]
Việc định nghĩa một biến có kiểu
struct cũng đơn giản như khi định nghĩa các biến bình thường:
struct person Bluesman; struct person Bio = { "Hieu", 30 };
Trong cách đầu thì biến Bluesman chưa có giá trị khởi động (nó vẫn có thể được truy cập và thay đổi giá trị sau này) trong khi biến Bio đã được gán các giá trị ban đầu. Hãy lưu ý dùng dấu phẩy "
," để phân biệt các giá trị được gán lên những thành phần của cấu trúc—và dĩ nhiên chúng phải có đúng kiểu cũng như không thể gán thiếu các giá trị cho các thành phần này.
Để truy cập đến các giá trị của biến có kiểu struct thì có thể dùng toán tử "." như câu lệnh sau:
printf("Name: %s\n", Bio.name);
### Mảng của các
struct[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=17) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=17)]
Để kiến tạo một mảng của các
struct thì dùng cú pháp sau:
struct person list[10];
### Con trỏ chỉ tới
struct[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=18) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=18)]
Cũng vậy, việc tiến hành khai báo một biến con trỏ có kiểu là
struct tương tự cách thông thường. Chỉ cần thêm vào đó dấu sao đằng trước tên biến:
struct person *Huong;
### Cấu trúc lồng nhau[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=19) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=19)]
Kiểu cấu trúc cũng có thể định nghĩa lồng vào nhau. Thí dụ dưới đây cho thấy việc khai báo cấu trúc
worker có chứa cấu trúc
person như là một thành phần. Việc truy cập dữ liệu thành phần của cấu trúc bên trong cũng được tiến hành theo cách dùng toán tử "." nối tiếp nhau.
struct person { char name[60]; int age; }; struct worker { struct person peronal_ID; char job[30]; float income; };
## Kiểu hợp nhất[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=20) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=20)]
Kiểu hợp nhất có tên từ khóa là
union kiểu đặc biệt này cho phép nó chứa dữ liệu mà có thể có kiểu khác nhau trong cùng một phần bộ nhớ (mà nó có thể được cấp phát khi khai báo biến):
union folder { int number; double real; char letter; }; //lưu ý dấu ";" cần dùng để kết thúc câu lệnh
Để khai báo biến, có thể dùng cách thông thường, tạo mảng các
union hay cách tham chiếu:
union folder matter; union folder listtype[100]; union folder *matterptr;
Để gán hay truy cập giá trị cho một biến union, có thể dùng toán tử "." Theo hàng khai báo đầu tiên của thí dụ trên ta có thể viết một trong các phép gán:
matter.real=3.1416;
hay là:
matter.letter = 't';
hay là:
matter.number = 1;
Lưu ý:
- Việc gán giá trị cho một biến kiểu
unionđòi hỏi kiểu của dữ liệu đó phải có mặt trong khai báo ban đầu của nó. Theo thí dụ trên thì kiểu
folderchỉ chấp nhận chứa một đơn vị dữ liệu của một trong ba kiểu
int, double,và
char.
- Một khi giá trị có kiểu đúng nào đó được gán cho một biến kiểu
unionthì nó sẽ xóa bỏ hẳn giá trị cũ (nếu có) mà biến này đã chứa trước đó.
- Việc truy cập một giá trị từ một biến kiểu
unioncần lưu ý đến kiểu hiện tại của dữ liệu đang được chứa của biến này nếu không, có thể gây ra lỗi dùng sai kiểu.
- Điểm khác nhau quan trọng giữa
unionvà
structlà
unionchỉ có được một thành phần (nhưng thành phần này phải có kiểu tùy theo khai báo của người lập trình) trong khi
structbao gồm nhiều thành phần (và mỗi thành phần có thể có kiểu khác nhau)
*.*
- Tương tự như
strruct,
unioncho phép khai báo nhiều union lồng nhau.
## Dùng
#define để định nghĩa hằng và kiểu[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=21) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=21)]
Một cách tổng quát thì từ khóa
[tiền xử lý](/wiki/Ti%E1%BB%81n_x%E1%BB%AD_l%C3%BD)
#define đùng để định nghĩa tên của một kiểu (đối tượng) nào đó. Thực ra, câu lệnh
#define chỉ là một loại câu lệnh
[macro](/wiki/Ng%C3%B4n_ng%E1%BB%AF_l%E1%BA%ADp_tr%C3%ACnh#MACRO). Có hai ứng dụng chính như sau:
### Định nghĩa tên hằng[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=22) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=22)]
Có thể dùng câu lệnh tiền xử lý
#define để định nghĩa một hằng:
#define PI 3.14159 //định nghĩa tên một hằng số PI #define STANDARD "ANSI C" //định nghĩa tên một hằng dãy kí tự #define ESC '\033' //định nghĩa tên một hằng kí tự mã ASCII của phím Esc.
Lưu ý: so với cách định nghĩa dùng từ khóa
[ thì cách dùng này không được uyển chuyển bằng nhưng nó thường cho hiệu quả thực thi nhanh hơn vì đây chỉ là các macro. const](#T.E1.BB.AB_kh.C3.B3a_.C4.91.E1.BB.8Bnh_t.C3.ADnh_const_cho_c.C3.A1c_ki.E1.BB.83u)
### Định nghĩa tên của kiểu dữ liệu[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=23) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=23)]
Có thể dùng
#define để định nghĩa tên của một kiểu dữ liệu:
#define real float //định nghĩa tên kiẻu real cho dữ liệu có kiểu float
Việc khai báo các biến không có gì khác lạ ngoại trừ tên mới được dùng:
real x, y[3], *z;
Lưu ý: Việc sử dụng
#define có thể có các hiệu ứng phụ không ngờ nếu dùng nó kết hợp với nhiều định tính và có thể dẫn đến những lỗi khó tìm khi viết mã:
#define STRING char *
Trong lúc định nghĩa biến người lập có thể muốn định nghĩa hai con trỏ
char như sau:
STRING name, job;
Tuy nhiên, điều ước muốn sẽ không xảy ra vì
#define là macro nên trình dịch sẽ diễn giải thành (nó chỉ thay thế tên
STRING bằng
char *):
char * name, job;
Và như vậy, người lập trình sẽ không nhận được hai biến con trỏ như dự tính mà chỉ có một biến
name là con trỏ mà thôi.
## Dùng
typedef để định nghĩa kiểu[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=24) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=24)]
Một cách khác để đặt tên riêng cho kiểu dữ liệu là dùng câu lệnh với từ khóa
typedef:
typedef float real;
Nếu so sánh cách viết trong thí dụ trên với việc dùng từ khoá
#define để định nghĩa thì chúng hoàn toàn tương đương (chỉ khác nhau về thứ tự các chữ
float và
real). Tuy nhiên, cách viết này là một sự thay thế thế tên "đúng nghĩa" chứ không phải là một macro đơn thuần. Trở lại thí dụ:
typedef char* string;
Câu lệnh trên cho phép đặt tên string như là một kiểu mới (mà nội dung của nó là kiểu con trỏ
char). Bây giờ hãy xét đến câu lệnh khai báo biến:
string name, job;
Trường hợp này sẽ được trình dịch diễn dịch đúng theo mong muốn thành:
char *name, *job;
### Dùng cho
struct[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=25) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=25)]
Một thí dụ khác liên quan đến việc đặt tên cho
struct là việc kết hợp cả hai khai báo và đặt tên lại trong cùng một câu lệnh:
typedef struct { char * name; int * age; } person;
Như vậy khi khai báo biến chỉ cần viết là:
person Trung;
### Ứng dụng[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=26) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=26)]
Một ứng dụng đáng lưu ý của
typedef là việc làm cho mã C trở nên linh hoạt hơn trong nhiều môi trường khác nhau. Thí dụ: khi muốn xác định dùng đúng 4 byte cho một kiểu nguyên nhưng trên một số hệ máy thì nó ứng với kiểu
int, trong khi trên một số hệ máy khác nó lại ứng với kiểu
long int. Để giải quyết việc dùng chính xác 4 byte cho kiểu nguyên mà người lập trình muốn, thì có thể dùng giải pháp là: thêm vào một
[tập tin bao gồm](/wiki/C_(ng%C3%B4n_ng%E1%BB%AF_l%E1%BA%ADp_tr%C3%ACnh)#INCLUDE) trong đó có chứa định nghĩa:
typedef int FOURBYTE; //dùng cho các máy lấy
intlà 4 byte
hay định nghĩa:
typedef long int FOURBYTE; //dùng cho các máy lấy
long intlà 4 byte
và chỉ cần thêm vào trong mã nguồn câu lệnh
#include <Tên_tập_tin_bao_gồm> như vậy chỉ cần thay nội dung của tập tin bao gồm thì toàn bộ mã vẫn hoạt động đúng.
## Kiểu
enum[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=27) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=27)]
Kiểu
enum là một kiểu dữ liệu đặc biệt được dùng để định nghĩa một quan hệ thứ tự cho một tập họp hữu hạn các tên. (Trong thực tế thì
enum có kiểu là
int—Theo trang 553 trong cuốn "New C Primer Plus"—xem thêm phần tham khảo):
enum Wiki {Arisa, Bluesman, VietBio, Trung, Quang, Minh};
Để khai báo biến
member có kiểu
enum dùng câu lệnh:
enum member;
Các giá trị (hiểu ngầm) của các kí hiệu
Arisa, Bluesman, VietBio, Trung, Quang, Minh theo mặc định sẽ tương ứng với 0, 1, 2, 3, 4, 5. Các câu lệnh cách viết sau đây là có hiệu lực:
member = Minh; if (member == VietBio) { do_some_commands } for (member=Arisa; member <= Trung; member++) { do_some_commands }
Như vậy, theo mặc định, các tên của một
enum được xem là các hằng số từ 0 tăng dần cho đến tên cuối cùng.
Tuy nhiên, C không loại trừ khả năng xếp lại giá trị của một kiểu
enum theo cách riêng:
enum reordert={duck,cat=10, mouse =50, elephant =1000, lion, virus};
Trong thí dụ trên thì
duck có giá trị tương ứng là 0,
cat là 10,...,
elephant là 1000, còn
lion tương ứng với giá trị 1001 và
virus tương ứng với 1002.
Một trong những ứng dụng chính của kiểu này là để tăng cường khả năng đọc mã được dễ hiểu hay phù hợp hơn.
## Kiểu
FILE[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=28) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=28)]
Kiểu
FILE là kiểu dữ liệu dùng để xử lí các tập tin. Theo ANSI thì có hai phương thức để truy cập là nhị phân (
*binary*) và văn bản ( *text*). Người ta dùng một biến con trỏ để khai báo:
FILE *fp;
Thủ tục quan trọng cần làm tiếp theo là việc mở tập tin. Hàm thường được dùng để mở tập tin là
fopen
fp = fopen ("Dung.txt", "r");
Trong dòng lệnh trên thì tập tin có tên
Dung.txt sẽ được mở trong chế độ đọc
r. Các chế độ truy cập cơ bản bao gồm:
r(đọc)
w(viết)
a(viết tiếp vào cuối tập tin và tạo tập tin mới nếu chưa có tập tin này)
r+(đọc và viết)
w+(đọc và viết nhưng cắt bỏ nội dung cũ của tập tin nếu có, tạo tập tin nếu nó chưa tồn tại)
a+
- Các chế độ
rb, wb, ab, rb+, r+b, wb+, w+b, ab+, a+bgiống như các trường hợp trên nhưng chỉ dùng cho tập tin nhị phân.
Để tiếp tục việc xử lí thì có thể dùng tới các hàm trong thư viện chuẩn như:
getc(), putc(), fprintf(), fscanf(), fgets(), fputs(), fseek(), ftell() và hàm
fclose().
## Lưu ý về biến được khai báo
static[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=29) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=29)]
Các biến có được xác định bởi định tính
static đặt trước tên kiểu biến khi khai báo sẽ cho biến đó một tính năng đặc biệt, đó là, giá trị của nó sẽ được lưu giữ không bị mất đi mặc dù khối mã chứa nó đã được xử lí xong. Trường hợp. Đặc biệt nếu một biến được khai báo có định tính
static trong một hàm và được cài đặt giá trị nào đó thì sau khi hàm đó được gọi, giá trị của biến
static đó vẫn còn giữ nguyên giữa mỗi lần gọi (cho tới khi nó được gán giá trị khác trong lần gọi tới của hàm). Thi dụ sau đây khai báo biến my_static có định tính
static trong một hàm:
#include<stdio.h> int static_func(int init) { static int my_static_var; my_static_var += init; return my_static_var; } int main(void) { printf("call the 1st time (init=0), my_static_var = %d\n", static_func(0)); printf("call the 2nd time (init=1), my_static_var = %d\n", static_func(1)); printf("call the 3rd time (init=2), my_static_var = %d\n", static_func(2)); }
Sau khi dịch và chạy mã này sẽ cho kết quả:
call the 1st time (init=0), my_static_var = 0 //0 +0 =0 call the 2nd time (init=1), my_static_var = 1 //0 +1 =1 call the 3rd time (init=2), my_static_var = 3 //1 +2 =3
Lưu ý: Mọi biến toàn cục đều có định tính
static một cách tự động.
## Xem thêm[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=30) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=30)]
## Tham Khảo[
[sửa](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&veaction=edit&vesection=31) | [sửa mã nguồn](/w/index.php?title=Ki%E1%BB%83u_v%C3%A0_khai_b%C3%A1o_bi%E1%BA%BFn_trong_C&action=edit§ion=31)]
- New C Primer Plus. The Waite Group's. SAM Publishing. 1993.
[ISBN 0-672-30319-1](/wiki/%C4%90%E1%BA%B7c_bi%E1%BB%87t:Ngu%E1%BB%93n_s%C3%A1ch/0672303191)

X-Cache: cp1066 miss(0), cp1054 frontend miss(0)


text:
Waterford, Pennsylvania
Bách khoa toàn thư mở Wikipedia
Waterford là một thị trấn thuộc quận Erie, tiểu bang Pennsylvania, Hoa Kỳ. Năm 2010, dân số của thị trấn này là 1517 người.[1]
Chú thích[sửa | sửa mã nguồn]
- ^ “2010 Census Gazetteer Files”. Cục Thống kê Dân số Hoa Kỳ. Truy cập ngày 22 tháng 10 năm 2012.

markdown:
# Waterford, Pennsylvania
Bách khoa toàn thư mở Wikipedia
|Waterford, Pennsylvania|
|—
|![ Hình nền trời của Waterford, Pennsylvania](//upload.wikimedia.org/wikipedia/commons/thumb/4/46/Waterford%2C_Pennsylvania.jpg/250px-Waterford%2C_Pennsylvania.jpg)
![ Hình nền trời của Waterford, Pennsylvania](http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Waterford%2C_Pennsylvania.jpg/250px-Waterford%2C_Pennsylvania.jpg)
![ Vị trí trong Quận Erie, Pennsylvania](//upload.wikimedia.org/wikipedia/commons/thumb/8/8a/Map_of_Waterford%2C_Erie_County%2C_Pennsylvania_Highlighted.png/250px-Map_of_Waterford%2C_Erie_County%2C_Pennsylvania_Highlighted.png)
![ Vị trí trong Quận Erie, Pennsylvania](http://upload.wikimedia.org/wikipedia/commons/thumb/8/8a/Map_of_Waterford%2C_Erie_County%2C_Pennsylvania_Highlighted.png/250px-Map_of_Waterford%2C_Erie_County%2C_Pennsylvania_Highlighted.png)
Vị trí trong
[Quận Erie](/wiki/Qu%E1%BA%ADn_Erie,_Pennsylvania), [Pennsylvania](/wiki/Pennsylvania) ![ Vị trí quận Erie trong tiểu bang Pennsylvania ở Hoa Kỷ](//upload.wikimedia.org/wikipedia/commons/thumb/1/16/Map_of_Pennsylvania_highlighting_Erie_County.svg/250px-Map_of_Pennsylvania_highlighting_Erie_County.svg.png)
![ Vị trí quận Erie trong tiểu bang Pennsylvania ở Hoa Kỷ](http://upload.wikimedia.org/wikipedia/commons/thumb/1/16/Map_of_Pennsylvania_highlighting_Erie_County.svg/250px-Map_of_Pennsylvania_highlighting_Erie_County.svg.png)
Vị trí quận Erie trong tiểu bang Pennsylvania ở Hoa Kỷ
[Quốc gia](/wiki/Qu%E1%BB%91c_gia) [Hoa Kỳ](/wiki/Hoa_K%E1%BB%B3) [Tiểu bang](/wiki/Ti%E1%BB%83u_bang_Hoa_K%E1%BB%B3) [Pennsylvania](/wiki/Pennsylvania) [Quận](/w/index.php?title=Danh_s%C3%A1ch_c%C3%A1c_qu%E1%BA%ADn_%E1%BB%9F_Pennsylvania&action=edit&redlink=1) [Quận Erie](/wiki/Qu%E1%BA%ADn_Erie,_Pennsylvania) [Múi giờ](/wiki/M%C3%BAi_gi%E1%BB%9D) [EST](/wiki/M%C3%BAi_gi%E1%BB%9D_mi%E1%BB%81n_%C4%90%C3%B4ng_(B%E1%BA%AFc_M%E1%BB%B9))( [UTC-5](/wiki/UTC-5)) [DST](/wiki/Quy_%C6%B0%E1%BB%9Bc_gi%E1%BB%9D_m%C3%B9a_h%C3%A8)) **EDT**( [UTC-4](/wiki/UTC-4)) **Waterford** là một [thị trấn](/wiki/Th%E1%BB%8B_tr%E1%BA%A5n) thuộc [quận Erie](/wiki/Qu%E1%BA%ADn_Erie,_Pennsylvania), tiểu bang [Pennsylvania](/wiki/Pennsylvania), [Hoa Kỳ](/wiki/Hoa_K%E1%BB%B3). Năm 2010, dân số của thị trấn này là 1517 người. [[1]](#cite_note-1)
## Chú thích[
[sửa](/w/index.php?title=Waterford,_Pennsylvania&veaction=edit&vesection=1) | [sửa mã nguồn](/w/index.php?title=Waterford,_Pennsylvania&action=edit§ion=1)] [^](#cite_ref-1) [“2010 Census Gazetteer Files”](http://www.census.gov/geo/www/gazetteer/gazetteer2010.html). [Cục Thống kê Dân số Hoa Kỳ](/wiki/C%E1%BB%A5c_Th%E1%BB%91ng_k%C3%AA_D%C3%A2n_s%E1%BB%91_Hoa_K%E1%BB%B3). Truy cập ngày 22 tháng 10 năm 2012.

WARC-Type: response

Content-Type: application/http; msgtype=response

Connection: close

X-Content-Type-Options: nosniff

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

Via: 1.1 varnish, 1.1 varnish

Content-Language: vi

X-UA-Compatible: IE=Edge

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

Vary: Accept-Encoding,Cookie

Accept-Ranges: bytes

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


text:
лихорадка
Từ điển mở Wiktionary
Tiếng Nga[sửa]
Chuyển tự[sửa]
Xem Wiktionary:Phiên âm của tiếng Nga.
Danh từ[sửa]
лихорадка gc
- (Cơn) Sốt; (с жаром) [cơn] sốt nóng; (с ознобом) [cơn] sốt rét, sốt run.
- жёлтая лихорадка — мед. — bệnh sốt vàng
- крапивная лихорадка — мед. — [phong] mày đay
- трястись в лихорадке — sốt rét run lẩy bẩy
- (перен.) [cơn] xúc động mạnh.
- военная лихорадка — [sự] ráo riết vũ trang
Tham khảo[sửa]
- Hồ Ngọc Đức, Dự án Từ điển tiếng Việt miễn phí (chi tiết)

markdown:
# лихорадка
Từ điển mở Wiktionary
## Tiếng Nga[
[sửa](/w/index.php?title=B%E1%BA%A3n_m%E1%BA%ABu:-rus-&action=edit§ion=T-1)]
### Chuyển tự[
[sửa](/w/index.php?title=B%E1%BA%A3n_m%E1%BA%ABu:-translit-&action=edit§ion=T-1)]
Xem
[Wiktionary:Phiên âm của tiếng Nga](/wiki/Wiktionary:Phi%C3%AAn_%C3%A2m_c%E1%BB%A7a_ti%E1%BA%BFng_Nga).
### Danh từ[
[sửa](/w/index.php?title=B%E1%BA%A3n_m%E1%BA%ABu:-noun-&action=edit§ion=T-1)] **лихор адка** gc
- (
*Cơn*) [Sốt](/wiki/s%E1%BB%91t); (с жаром) [cơn] [sốt](/wiki/s%E1%BB%91t) [nóng](/wiki/n%C3%B3ng); (с ознобом) [cơn] [sốt rét](/wiki/s%E1%BB%91t_r%C3%A9t), [sốt](/wiki/s%E1%BB%91t) [run](/wiki/run). *жёлтая*— **лихорадка** *мед.*— bệnh sốt vàng *крап*— __и__вная **лихорадка** *мед.*— [phong] mày đay *тряст*— sốt rét run lẩy bẩy __и__сь в **лихор** __а__дке
-
- (
*перен.*) [cơn] [xúc động](/wiki/x%C3%BAc_%C4%91%E1%BB%99ng) [mạnh](/wiki/m%E1%BA%A1nh). *во*— [sự] ráo riết vũ trang __е__нная **лихорадка**
-
### Tham khảo[
[sửa](/w/index.php?title=B%E1%BA%A3n_m%E1%BA%ABu:-ref-&action=edit§ion=T-1)]
- Hồ Ngọc Đức,
[Dự án Từ điển tiếng Việt miễn phí](http://www.informatik.uni-leipzig.de/~duc/Dict/)( [chi tiết](/wiki/Wiktionary:Ngu%E1%BB%93n_g%E1%BB%91c/FVDP))

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


text:
aviary
Từ điển mở Wiktionary
Bước tới:
dẫn lái
,
tìm
Mục lục
1
Tiếng Anh
1.1
Cách phát âm
1.2
Danh từ
1.3
Tham khảo
Tiếng Anh
[
sửa
]
Cách phát âm
[
sửa
]
IPA
:
/ˈeɪ.vi.ˌɛr.i/
Danh từ
[
sửa
]
aviary
/ˈeɪ.vi.ˌɛr.i/
Chuồng
chim
.
Tham khảo
[
sửa
]
Hồ Ngọc Đức,
Dự án Từ điển tiếng Việt miễn phí
(
chi tiết
)
Lấy từ “
https://vi.wiktionary.org/w/index.php?title=aviary&oldid=1620999
”
Thể loại
:
Mục từ tiếng Anh
Danh từ
Danh từ tiếng Anh
Trình đơn chuyển hướng
Công cụ cá nhân
Chưa đăng nhập
Thảo luận
Đóng góp
Mở tài khoản
Đăng nhập
Không gian tên
Mục từ
Thảo luận
Biến thể
Các hiển thị
Tra
Sửa đổi
Xem lịch sử
Khác
Tìm kiếm
Chuyển hướng
Trang Chính
Cộng đồng
Thay đổi gần đây
Mục từ ngẫu nhiên
Trợ giúp
Thảo luận chung
Quyên góp
Chỉ mục
Ngôn ngữ
Chữ cái
Bộ thủ
Từ loại
Chuyên ngành
In/xuất ra
Tạo một quyển sách
Tải về dưới dạng PDF
Bản in được
Công cụ
Các liên kết đến đây
Thay đổi liên quan
Tải tập tin lên
Các trang đặc biệt
Liên kết thường trực
Thông tin trang
Trích dẫn trang này
Ngôn ngữ định nghĩa
English
Eesti
Suomi
Français
Magyar
Հայերեն
Ido
Italiano
ಕನ್ನಡ
한국어
Kurdî
മലയാളം
မြန်မာဘာသာ
Polski
Slovenčina
தமிழ்
తెలుగు
Trang này được sửa đổi lần cuối lúc 11:10 ngày 5 tháng 9 năm 2015.
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.
Quy định quyền riêng tư
Giới thiệu Wiktionary
Lời phủ nhận
Nhà phát triển
Cookie statement
Phiên bản di động

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


text:
Thông báo tổng hợp 17-09-2015
vozForums
>
Đại sảnh
>
Tin tức iNet
Lumia 920 giá tầm 15,5 triệu đồng, bán từ tháng 11
User Name
Remember Me?
Password
FAQ
Social Groups
Calendar
Mark Forums Read
Page 7 of 10
«
First
<
5
6
7
8
9
>
Last
»
Thread Tools
#
61
13-09-2012, 23:05
flowerfx3
K.I.A
Join Date: 08-2012
Posts: 411
Re: Lumia 920 giá tầm 15,5 triệu đồng, bán từ tháng 11
Quote:
Originally Posted by
chungvodim1
Đợi M$ nó tung ra WP8 SDK thì tụi developers không xoắn tít lên vì sướng mới là lạ đó
có wp8 sdk rồi, nhưng mà vẫn phải update lên tiếp nữa
hiện chỉ dừng đến việc hộ trợ đến win 8 RTM , còn về sau đợi thằng w8 ra hẳn hoi rồi xem
//nhưng mà API cho w8 cũng có thể gần hoàn thiện chỉ có 1 vài phần chưa bổ xung ví dụ như xbox live là đang làm
flowerfx3
View Public Profile
Find all posts by flowerfx3
#
62
13-09-2012, 23:48
cong1181
K.I.A
Join Date: 11-2009
Posts: 3,002
Re: Lumia 920 giá tầm 15,5 triệu đồng, bán từ tháng 11
920 mà giá này thì iphone với HTC nó đè cho bẹp ruột. Mình đang dùng 710, thấy WP rất phù hợp và rất sướng, nhưng mà nếu chát qúa thì sang dùng cảu HTC cho nó tiết kiệm
cong1181
View Public Profile
Find all posts by cong1181
#
63
13-09-2012, 23:57
big_b0ss
Senior Member
Join Date: 09-2011
Posts: 1,752
Re: Lumia 920 giá tầm 15,5 triệu đồng, bán từ tháng 11
Quote:
Originally Posted by
cong1181
920 mà giá này thì iphone với HTC nó đè cho bẹp ruột. Mình đang dùng 710, thấy WP rất phù hợp và rất sướng, nhưng mà nếu chát qúa thì sang dùng cảu HTC cho nó tiết kiệm
Con iP5 gần như thua đứt L920 mà về VN giá nó cao hơn giá L920 có thấy ai kêu mắc đâu, lại còn được khen rẻ vì "cấu hình hơn iP4S mà giá chỉ bằng iP4S lúc trước"
big_b0ss
View Public Profile
Send a private message to big_b0ss
Find all posts by big_b0ss
#
64
14-09-2012, 00:40
chungvodim1
Senior Member
Join Date: 09-2010
Posts: 384
Re: Lumia 920 giá tầm 15,5 triệu đồng, bán từ tháng 11
Quote:
Originally Posted by
big_b0ss
Con iP5 gần như thua đứt L920 mà về VN giá nó cao hơn giá L920 có thấy ai kêu mắc đâu, lại còn được khen rẻ vì "cấu hình hơn iP4S mà giá chỉ bằng iP4S lúc trước"
Công nhận rất nhiều thằng thiếu muỗi phát biểu câu này
Quote:
cấu hình hơn iP4S mà giá chỉ bằng iP4S lúc trước
. Không hiểu chúng nó học được ở đâu kiểu phân tích siêu việt đến thế
chungvodim1
View Public Profile
Send a private message to chungvodim1
Find all posts by chungvodim1
#
65
14-09-2012, 01:02
Terrorblade
Đã tốn tiền
Join Date: 03-2012
Location: Sanctuary
Posts: 3,433
Re: Lumia 920 giá tầm 15,5 triệu đồng, bán từ tháng 11
Quote:
Originally Posted by
chungvodim1
Công nhận rất nhiều thằng thiếu muỗi phát biểu câu này . Không hiểu chúng nó học được ở đâu kiểu phân tích siêu việt đến thế
nói có sách mách có chứng đây
Last edited by Terrorblade; 14-09-2012 at
01:06
.
Terrorblade
View Public Profile
Send a private message to Terrorblade
Find all posts by Terrorblade
#
66
14-09-2012, 03:11
TheSunOfVN
Đã tốn tiền
Join Date: 02-2009
Posts: 1,244
Re: Lumia 920 giá tầm 15,5 triệu đồng, bán từ tháng 11
Quote:
Processor: 1.5 GHz dual core Qualcomm Snapdragon S4 processor
Battery: Integrated BP-4GW battery (2000 mAh)
Wireless charging support
Network: GSM, LTE, WCDMA
Ngon phết nhỉ. Các thím cho hỏi lúc trước đọc bài về WP7 ko lên đc WP8 do bộ chip khác thì sao M$ ko port lại cho các máy dùng WP7 có thể lên WP8 nhỉ? Hay WP8 yêu cầu cấu hình cao hơn các máy WP7 hiện tại
TheSunOfVN
View Public Profile
Send a private message to TheSunOfVN
Find all posts by TheSunOfVN
#
67
14-09-2012, 03:54
Jerry Frz
Senior Member
Join Date: 08-2012
Posts: 426
Re: Lumia 920 giá tầm 15,5 triệu đồng, bán từ tháng 11
Quote:
Originally Posted by
TheSunOfVN
Ngon phết nhỉ. Các thím cho hỏi lúc trước đọc bài về WP7 ko lên đc WP8 do bộ chip khác thì sao M$ ko port lại cho các máy dùng WP7 có thể lên WP8 nhỉ? Hay WP8 yêu cầu cấu hình cao hơn các máy WP7 hiện tại
Kernel của WP8 khác WP7
Jerry Frz
View Public Profile
Send a private message to Jerry Frz
Find all posts by Jerry Frz
#
68
14-09-2012, 05:20
how.to.escape
Senior Member
Join Date: 02-2012
Posts: 1,702
Re: Lumia 920 giá tầm 15,5 triệu đồng, bán từ tháng 11
Quote:
Originally Posted by
Troll Genius
Nghe cái giá mà run cả tay. Thế này khó bay đây @@
Đọc giá trên các site nước ngoài toàn tầm 16+ triệu... Nên 15.5 triệu là giá ngon rồi! SP flagship mà làm như là đồ bỏ ấy!
IP5 có hơn gì ngoài cái thương hiệu ảo và 1 sự ủng hộ có phần mù quáng, thì những 2x triệu vẫn có người mua...
IP5 giả như giảm còn 15tr, còn Lumia 920 là 13.9-14.5tr chẳng hạn, thì Lumia 920 vẫn đáng mua hơn chứ.
Last edited by how.to.escape; 14-09-2012 at
05:23
.
how.to.escape
View Public Profile
Send a private message to how.to.escape
Find all posts by how.to.escape
#
69
14-09-2012, 05:22
how.to.escape
Senior Member
Join Date: 02-2012
Posts: 1,702
Re: Lumia 920 giá tầm 15,5 triệu đồng, bán từ tháng 11
Quote:
Originally Posted by
cong1181
920 mà giá này thì iphone với HTC nó đè cho bẹp ruột. Mình đang dùng 710, thấy WP rất phù hợp và rất sướng, nhưng mà nếu chát qúa thì sang dùng cảu HTC cho nó tiết kiệm
Đây, chắc lại i-fan.
Đọc lại comment phía trên xem.
how.to.escape
View Public Profile
Send a private message to how.to.escape
Find all posts by how.to.escape
#
70
14-09-2012, 06:05
darkpanther
Đã tốn tiền
Join Date: 11-2011
Posts: 2,155
Re: Lumia 920 giá tầm 15,5 triệu đồng, bán từ tháng 11
Quote:
Originally Posted by
how.to.escape
Đọc giá trên các site nước ngoài toàn tầm 16+ triệu... Nên 15.5 triệu là giá ngon rồi! SP flagship mà làm như là đồ bỏ ấy!
IP5 có hơn gì ngoài cái thương hiệu ảo và 1 sự ủng hộ có phần mù quáng, thì những 2x triệu vẫn có người mua...
IP5 giả như giảm còn 15tr, còn Lumia 920 là 13.9-14.5tr chẳng hạn, thì Lumia 920 vẫn đáng mua hơn chứ.
15 chai mà kèm theo thuế nhập khẩu với GTGT thì cũng chua lắm đấy, WP còn mới, thiếu app, khó mà cự lại với Apple hay SS.
darkpanther
View Public Profile
Send a private message to darkpanther
Find all posts by darkpanther
Page 7 of 10
«
First
<
5
6
7
8
9
>
Last
»
«
Previous Thread
|
Next Thread
»
Thread Tools
Show Printable Version
Email this Page
Posting Rules
You
may not
post new threads
You
may not
post replies
You
may not
post attachments
You
may not
edit your posts
BB code
is
On
Smilies
are
On
[IMG]
code is
On
HTML code is
Off
Forum Rules
Forum Jump
User Control Panel
Private Messages
Subscriptions
Who's Online
Search Forums
Forums Home
Đại sảnh
Thông báo
Thắc mắc & Góp ý
Thread post sai mục
Tin tức iNet
Review sản phẩm
Máy tính để bàn
Overclocking & Cooling
Modding
AMD
Intel
Mainboard & Memory
Đồ họa máy tính
Phần cứng chung
Thiết bị ngoại vi & Phụ kiện
Game máy tính
MMO -- Game Online
Liên Minh Huyền Thoại
Phần mềm
Download
Phát triển Phần mềm
Trường đua
Sản phẩm công nghệ
Máy tính xách tay
Tất tần tật thông tin về Dell anh em cần biết
Các sản phẩm Apple
Máy tính chuyên dụng
Thiết bị di động
Đồ điện tử & Thiết bị gia dụng
Multimedia
HDmedia
Giao lưu Doanh nghiệp & Người dùng (theo Alphabet)
DELL - Thông tin sản phẩm và dịch vụ chính hãng
Công ty TNHH TM-DV vi tính Hoàng Long
DiDong.Net - Game Mobile
Hoanghamobile.com
Công ty TNHH Thương mại Quốc tế Thủy Linh
Công ty cổ phần máy tính Vĩnh Xuân
WD - Thương hiệu ổ cứng tin cây, dịch vụ hỗ trợ tốt nhất
We can do
ZOTAC Việt Nam - Công ty Công nghệ Đạt Khang
Khu vui chơi giải trí
Chuyện trò linh tinh™
Superthreads
From f17 with Love
Offline
Các món ăn chơi
Trưng cầu dân ý
Khu thương mại - Mua và Bán
Máy tính để bàn
Máy tính xách tay
Điện thoại di động
Các thiết bị công nghệ khác
All times are GMT +7. The time now is
23:44
.
Contact Us
-
vozExpress
-
Archive
-
Top
Steam Powered by vBulletin® 0.1 pre-alpha
Copyright ©2000 - 2016, Jelsoft Enterprises Ltd.

WARC-Truncated: length

Set-Cookie: vflastactivity=0; expires=Tue, 07-Feb-2017 16:44:06 GMT; path=/; domain=vozforums.com; secure

Cache-Control: private, post-check=0, pre-check=0, max-age=0

Pragma: no-cache


text:
Thông báo tổng hợp 17-09-2015
vozForums
vBulletin Message
User Name
Remember Me?
Password
FAQ
Social Groups
Calendar
Mark Forums Read
vBulletin Message
Invalid Thread specified. If you followed a valid link, please notify the
administrator
Forum Jump
User Control Panel
Private Messages
Subscriptions
Who's Online
Search Forums
Forums Home
Đại sảnh
Thông báo
Thắc mắc & Góp ý
Thread post sai mục
Tin tức iNet
Review sản phẩm
Máy tính để bàn
Overclocking & Cooling
Modding
AMD
Intel
Mainboard & Memory
Đồ họa máy tính
Phần cứng chung
Thiết bị ngoại vi & Phụ kiện
Game máy tính
MMO -- Game Online
Liên Minh Huyền Thoại
Phần mềm
Download
Phát triển Phần mềm
Trường đua
Sản phẩm công nghệ
Máy tính xách tay
Tất tần tật thông tin về Dell anh em cần biết
Các sản phẩm Apple
Máy tính chuyên dụng
Thiết bị di động
Đồ điện tử & Thiết bị gia dụng
Multimedia
HDmedia
Giao lưu Doanh nghiệp & Người dùng (theo Alphabet)
DELL - Thông tin sản phẩm và dịch vụ chính hãng
Công ty TNHH TM-DV vi tính Hoàng Long
DiDong.Net - Game Mobile
Hoanghamobile.com
Công ty TNHH Thương mại Quốc tế Thủy Linh
Công ty cổ phần máy tính Vĩnh Xuân
WD - Thương hiệu ổ cứng tin cây, dịch vụ hỗ trợ tốt nhất
We can do
ZOTAC Việt Nam - Công ty Công nghệ Đạt Khang
Khu vui chơi giải trí
Chuyện trò linh tinh™
Superthreads
From f17 with Love
Offline
Các món ăn chơi
Trưng cầu dân ý
Khu thương mại - Mua và Bán
Máy tính để bàn
Máy tính xách tay
Điện thoại di động
Các thiết bị công nghệ khác
All times are GMT +7. The time now is
23:52
.
Contact Us
-
vozExpress
-
Archive
-
Top
Steam Powered by vBulletin® 0.1 pre-alpha
Copyright ©2000 - 2016, Jelsoft Enterprises Ltd.

Set-Cookie: vflastactivity=0; expires=Tue, 07-Feb-2017 16:52:10 GMT; path=/; domain=vozforums.com; secure