Sách C/Khai báo dữ liệu
Khai báo dữ liệu
[sửa]Các kiểu dữ liệu cơ bản
[sửa]Nhiều ngôn ngữ lập trình kể cả C, biểu thị các số trong hai dạng: nguyên và thực (hay không nguyên). Sự khác nhau này hình thành từ khía cạnh kỹ thuật của các cách thức xử lý và lưu trữ các giá trị trong bộ nhớ.
int
được dùng để biểu thị các số nguyên. Kiểu nguyên có trong nhiều kích cỡ khác nhau tùy theo phân lượng bộ nhớ được dùng và độ lớn cao nhấtBản mẫu:Ref 1. Các từ khóa, có tên là các định tính, được dùng thêm vào để điều chỉnh lại kích cỡ là: short
, long
và long long
Bản mẫu:Ref 2. Kiểu kí tự mà từ khóa của nó là char
, biểu thị đơn vị nhỏ nhất có thể địa chỉ hóa được (bởi kiến trúc máy tính) thường là một byte với 8 bit.Dạng thực được dùng để biểu thị các số thập phân hay các bộ phận hữu tỉ. Mặc dù vậy chúng không hoàn toàn chính xác mà chỉ là các biểu thị gần đúng.
Có 3 kiểu giá trị thực bao gồm: loại có độ chính xác đơn (có đặc tả là float
), loại có độ chính xác kép (có đặc tả là double
), và loại có độ chính xác kép mở rộng (có đặc tả là long double
). Mỗi loại dùng để biểu thị các giá trị không nguyên trong một dạng khác nhau.
Các kiểu nguyên có thể hoặc là có dấu (signed
) hay không dấu (unsigned
). Nếu không chỉ rõ khi khai báo thì mặc định (hiểu ngầm) sẽ là loại có dấu. Một ngoại lệ là các kiểu char
, signed char
và unsigned char
đều khác nhau, và kiểu char
có thể là loại có dấu hay không có dấu.
Đối với loại có dấu, thì bit
có nghĩa cao nhất được dùng để biểu thị dấu (dương hay âm). Thí dụ một số nguyên 16-bit loại có dấu thì chỉ dùng 15 bit để biểu thị giá trị (tuyệt đối) của nó còn bit có nghĩa cao nhất lại được dùng để cho biết đó là số dương hay âm. Đối với loại không dấu thì bit này lại được dùng thêm vào để biểu thị giá trị.
Bản mẫu:Ref 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)
Bản mẫu:Ref 2 = Từ khóa long long
được đưa thêm vào trong chuẩn C99.
Các hằng số xác định các giá trị biên
[sửa]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.
Đặ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 int
|
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
|
long long Bản mẫu:Ref 1
|
signed long long int Bản mẫu:Ref 1
|
LLONG_MIN Bản mẫu:Ref 2
|
LLONG_MAX Bản mẫu:Ref 2
|
unsigned long long Bản mẫu:Ref 1
|
unsigned long long int Bản mẫu:Ref 1
|
0 | ULLONG_MAX Bản mẫu:Ref 2
|
Bản mẫu:Ref 1— Định tính long long
chỉ được hỗ trợ trong các trình dịch thỏa mãn chuẩn C99.
Bản mẫu:Ref 2— Các hằng LLONG_MIN
, LLONG_MAX
, và ULLONG_MAX
chỉ được định nghĩa trong limits.h
nếu trình dịch tương ứng thỏa mãn chuẩn C99.
Các giá trị biên điển hình
[sửa]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.
Đặ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 |
long long Bản mẫu:Ref 1
|
signed long long int Bản mẫu:Ref 1
|
64 | 8 | -9 223 372 036 854 775 808 | 9 223 372 036 854 775 807 |
unsigned long long Bản mẫu:Ref 1
|
unsigned long long int Bản mẫu:Ref 1
|
64 | 8 | 0 | 18 446 744 073 709 551 615 |
Bản mẫu:Ref 1— Định tính long long
chỉ được hỗ trợ trong các trình dịch thỏa mãn chuẩn C99.
Kích cỡ và giới hạn của kiểu cơ bản int
(mà không có các định tính short
, long
, hay long long
) có thể thay đổi khác nhau (nhiều hơn các kiểu nguyên khác) tùy theo sư thiết lập (của trình dịch hay của kiến trúc máy). Cho nên, một thao tác thông thường là định nghĩa nó như là một đồng nghĩa của size_t
— trong tập tin sys/types.h
— và do đó, đủ sức để thích ứng với giá trị lớn nhất khả dĩ của con trỏ mà có thể được cấp phát bởi hệ thống. Đặc tả UNIX đơn chỉ ra rằng kiểu int
phải có ít nhất 32 bit, mặc dù chuẩn ISO C chỉ yêu cầu có 16 bit.
Các kiểu tham chiếu
[sửa]Tiền tố kí tự *
được dùng để biểu thị kiểu tham chiếu, mà thường được biết đến như là một con trỏ. Nếu như đặc tả int
biểu thị một kiểu nguyên cơ bản thì đặc tả int *
lại biểu thị một tham chiếu kiểu nguyên, tức là một loại con trỏ. Các giá trị tham chiếu tương quan sẽ bao gồm hai phần thông tin: đó là địa chỉ của vùng nhớ và một kiểu dữ liệu. Câu lệnh sau đây khai báo một biến tham chiếu nguyên có tên là ptr
:
int *ptr;
Sự tham chiếu
[sửa]Khi một con trỏ địa phương được khai báo, thì chưa có một địa chỉ nào gán cho nó cả. Địa chỉ tương quan với một con trỏ có thể được thay đổi (hay hình thành) qua phép gán. Trong thí dụ sau, biến ptr
sẽ cài cho nó chỉ tới cùng một dữ liệu như là biến nguyên cơ bản a
:
int *ptr; int a; ptr = &a;
Để làm được việc này, toán tử tham chiếu (hay còn gọi là tham chiếu ngược) &
đã được dùng tới. Nó trả về vị trí của biến trong bộ nhớ (tức là địa chỉ) hay là chỗ chứa thực thể theo sau (trong thí dụ thì thực thể đó là a). Toán tử này như là công việc nó làm thường đuợc gọi là toán tử "địa chỉ".
Trong trường hợp tổng quát, cụm từ giá trị tham chiếu được dùng để nói về địa chỉ trong bộ nhớ của sự tham chiếu (hay tham chiếu ngược).
Sự tham chiếu ngược
[sửa]Cùng một biểu hiện, giá trị có thể đọc về từ một giá trị tham chiếu. Trong thí dụ sau, biến nguyên cơ bản b
sẽ được gán đến dữ liệu mà dữ liệu đó được tham chiếu bởi ptr
:
int *ptr; int a, b; a = 10; //gán cho a giá trị là 10 ptr = &a; //phép gán địa chỉ của a (tức là &a) lên con trỏ 'ptr' //để ptr bây giờ chỉ đến địa chỉ có nội dung là 10 b = *ptr //phép gán này cho b một giá trị nằm ở địa chỉ mà 'ptr' //chỉ tới tức là giá trị của b sẽ là 10
Để hoàn tất được thao tác này, toán tử tham chiếu ngược (&
) đã được dùng. Nó trả về dữ liệu cơ bản. Dữ liệu này có giá trị là một tham chiếu chỉ tới (tức là một địa chỉ). Biểu thức *ptr
là một cách viết khác của giá trị 10 (gán cho b).
Việc quá tải của kí tự * có hai biểu hiện liên hệ mà có thể gây ra sự nhầm lẫn. Hiểu được sự khác nhau giữa việc dùng nó như là một tiền tố trong một khai báo (con trỏ) và việc xem nó là toán tử tham chiếu trong một biểu thức là rất quan trọng.
Sự tham chiếu tương đương và các mệnh đề cơ bản
[sửa]Bảng sau đây là danh sách các mệnh đề tương đương giữa kiểu cơ bản và kiểu tham chiếu (hay tham chiếu ngược). Trong đó, biến cơ bản d
và biến tham chiếu ptr
được hiểu ngầm.
Đến một giá trị cơ bản | Đến một giá trị tham chiếu | |
---|---|---|
Từ một giá trị cơ bản | d
|
&d
|
Từ một giá trị tham chiếu | *ptr
|
ptr
|