Ngân hàng câu hỏi của chương

Câu hỏi: PRF192 - Phần 2: Biến, kiểu dữ liệu, toán tử và biểu thức

47 câu trắc nghiệm kèm lời giải của môn PRF192 - Cơ sở lập trình, xếp theo thứ tự nhập vào ngân hàng.

Danh sách câu hỏi

20/47 câuCòn 27
Aconst
Bdefine
Cconstant
Dnamed
Lời giải
Đáp án đúng gồm hai ý: "const" và "define". Trong C có hai cách đặt tên cho một giá trị bất biến: từ khoá const gắn vào khai báo biến, bắt trình biên dịch chặn mọi phép gán lại; và chỉ thị tiền xử lý #define, thay tên bằng dãy ký tự giá trị trước khi biên dịch. Cần công bố một khuyết điểm của đề: câu ghi rõ chọn hai nhưng bản khoá in kèm chỉ tô được một ô, nên lời giải này dựng lại cặp đáp án từ chính quy tắc của ngôn ngữ chứ không đọc được từ khoá. "constant" không phải từ khoá của C, nó chỉ là từ tiếng Anh chỉ khái niệm hằng, viết vào mã sẽ bị xem là tên tự đặt và gây lỗi. "named" cũng không phải từ khoá, nó chỉ là tính từ trong cụm hằng có tên, trình biên dịch không hiểu gì.
Mở trang câu hỏi này →
Ax < z && y < z
Bx < z || y < z
Cy > x || y > z
Dy < z && z < x
Lời giải
Đáp án đúng: "x < z || y < z". Toán tử hoặc chỉ cần một vế đúng là cả biểu thức đúng, nên khi y < z đã đúng thì biểu thức này đúng bất kể x mang giá trị nào; dù vế đầu sai, vế sau vẫn được xét và cho kết quả đúng. "x < z && y < z" chưa chắc đúng vì toán tử và đòi cả hai vế đúng, mà quan hệ giữa x và z thì đề không cho biết. "y > x || y > z" không suy ra được: y > z chắc chắn sai vì đã có y < z, còn y > x thì không có dữ kiện nào bảo đảm. "y < z && z < x" cũng phụ thuộc điều kiện chưa biết, nó đòi thêm z < x mới đúng, nên hoàn toàn có thể sai.
Mở trang câu hỏi này →
ACompiler instructions
BDebug information
CBinary data
DMemory addresses of other programs
Lời giải
Đáp án đúng: "Binary data". Biến là một vùng ô nhớ được đặt tên, mà bộ nhớ chỉ lưu được các bit, nên mọi thứ nằm trong biến đều là dữ liệu nhị phân; kiểu của biến chỉ là cách trình biên dịch quy định đọc dãy bit đó thành số nguyên, số thực hay ký tự. "Compiler instructions" sai vì chỉ thị dành cho trình biên dịch tồn tại trong mã nguồn và biến mất sau khi dịch, chúng không được lưu vào biến lúc chạy. "Debug information" sai vì thông tin gỡ lỗi nằm ở các phần riêng của tệp thực thi do trình biên dịch sinh ra, không nằm trong biến của chương trình. "Memory addresses of other programs" sai vì một biến con trỏ chỉ giữ địa chỉ trong không gian nhớ của chính tiến trình này; hệ điều hành không cho chương trình này chạm vào vùng nhớ của chương trình khác.
Mở trang câu hỏi này →
AIdentification
BName
CDeclaration
DDefinition
Lời giải
Đáp án đúng: "Declaration". Khai báo là câu lệnh cho trình biên dịch biết một tên sẽ tồn tại và mang kiểu gì; nhờ có kiểu, trình biên dịch mới biết dành bao nhiêu byte và hiểu dãy bit ấy theo nghĩa nào, nên thuật ngữ chỉ việc nêu đồng thời kiểu và tên chính là khai báo. "Identification" không phải thuật ngữ của C cho việc này; từ gần nó là identifier, chỉ riêng cái tên do người viết đặt. "Name" chỉ nói tới phần tên, không mang thông tin kiểu, nên không đủ để trình biên dịch làm việc. "Definition" là bước mạnh hơn, nó vừa khai báo vừa cấp chỗ thật trong bộ nhớ hoặc viết thân hàm; với hàm thì nguyên mẫu đặt ở đầu tệp là khai báo, còn phần thân mới là định nghĩa.
Mở trang câu hỏi này →
AIt improves code portability
BIt makes the code shorter
CIt prevents the use of symbolic names
DIt increases code complexity
Lời giải
Đáp án đúng: "It improves code portability". Giá trị thần bí nằm rải rác trong mã là nguồn lỗi khi phải chuyển chương trình sang môi trường khác; đặt tên cho nó bằng #define thì mọi nơi dùng chung một chỗ sửa, nên khi kích thước bộ đệm hay giới hạn của một kiểu thay đổi theo máy, chỉ cần sửa một dòng là cả chương trình thích ứng. "It makes the code shorter" sai vì tên có nghĩa thường dài hơn con số nó thay; lợi ích nằm ở chỗ dễ đọc và sửa một nơi, không ở số ký tự. "It prevents the use of symbolic names" sai ngược hẳn, bởi #define chính là công cụ tạo ra tên tượng trưng. "It increases code complexity" sai vì thay con số vô nghĩa bằng tên nói rõ ý làm mã dễ hiểu hơn, độ phức tạp giảm chứ không tăng.
Mở trang câu hỏi này →
A16
B28
C37
D32
E-28
Lời giải
Đáp án đúng: "37". Với a bằng 8, b bằng 6, c bằng 4, biểu thức b++ * ++c + --a chạy như sau: b++ dùng giá trị cũ 6 rồi mới tăng b lên 7; ++c tăng c thành 5 rồi dùng 5; --a giảm a thành 7 rồi dùng 7; phép nhân làm trước phép cộng nên kết quả là 6 nhân 5 cộng 7, tức 37. Cốt lõi là hậu tố trả về giá trị trước khi tăng, còn tiền tố trả về giá trị sau khi tăng. "16" không thể ra được vì riêng phép nhân đã ít nhất 6 nhân 4 là 24, cộng thêm số dương thì càng xa. "28" ứng với việc lấy b sau khi tăng là 7 nhân c trước khi tăng là 4 rồi bỏ hẳn hạng tử --a. "32" ứng với việc bỏ qua cả hai toán tử tăng, tính 6 nhân 4 cộng 8. "-28" đòi một hạng tử âm, mà cả ba biến đều dương nên không phép nào sinh ra dấu trừ.
Mở trang câu hỏi này →
7What is the output?4 lựa chọncó code
Đề bài
int a = 8;
int b = 3;
int result = a % b * 2;
printf("%d", result);
A2
B4
C1
D5
Lời giải
Đáp án đúng: "4". Phép lấy dư và phép nhân cùng mức ưu tiên nên biểu thức a % b * 2 được tính từ trái sang phải: 8 % 3 cho 2 vì 8 chia 3 được 2 dư 2, rồi 2 nhân 2 cho 4, nên chương trình in 4. Thứ tự này là bản chất của ngôn ngữ, không phải quy ước toán học quen tay. "2" là giá trị của riêng 8 % 3, tức bỏ mất phép nhân 2 phía sau. "1" ứng với việc chia kết quả cho 2 bằng phép chia nguyên thay vì nhân, hoặc hiểu sai phần dư của 8 cho 3. "5" ứng với việc coi dấu phần trăm là phép trừ, lấy 8 trừ 3; trong C dấu đó chỉ có nghĩa lấy phần dư của phép chia nguyên và chỉ dùng được với toán hạng nguyên.
Mở trang câu hỏi này →
8What will be the output of the following C code?4 lựa chọncó code
Đề bài
#include <stdio.h>
int main()
{
    int a,b,c;
    a = b = c = 10;
    c = a++ || ++b && ++c;
    printf("%d %d %d",c, a, b);
    return 0;
}
A1 11 10
B10 11 1
C10 11 10
D1 1 10
Lời giải
Đáp án đúng: "1 11 10". Toán tử và kết chặt hơn toán tử hoặc, nên biểu thức được hiểu là a++ || (++b && ++c). Phép a++ trả về giá trị cũ 10, khác 0 nên vế trái đã đúng; toán tử hoặc rút mạch nên vế phải không được tính lần nào, do đó b giữ nguyên 10 và c không hề tăng. Giá trị của cả biểu thức luận lý là 1, và chính 1 đó được gán cho c, còn a đã tăng thành 11; thứ tự in là c, a, b nên ra 1 11 10. Cần công bố khuyết điểm: bản khoá in kèm ghi 10 11 10, giá trị đó chỉ đúng nếu phép gán nhận giá trị của a thay vì giá trị chân lý của biểu thức, nên "10 11 10" sai. "10 11 1" vừa gán sai cho c vừa đổi chỗ b với c khi in. "1 1 10" sai vì a đã tăng thành 11, không thể còn 1.
Mở trang câu hỏi này →
Aint _a3;
Bint a_3;
Cint 3_a;
Dint _3a
Lời giải
Đáp án đúng: "int 3_a;". Quy tắc đặt tên trong C bắt buộc định danh phải bắt đầu bằng chữ cái hoặc dấu gạch dưới, các ký tự sau đó mới được phép là chữ số. Lý do nằm ở bộ phân tích từ vựng: gặp ký tự số đứng đầu, nó cố đọc một hằng số, nên 3_a bị nhận là số 3 dính thêm phần rác phía sau và trình biên dịch báo lỗi cú pháp. Ý "int _a3;" hợp lệ vì mở đầu bằng dấu gạch dưới, sau đó là chữ và số. Ý "int a_3;" hợp lệ vì mở đầu bằng chữ cái, còn dấu gạch dưới và chữ số đều được phép đứng ở giữa tên. Ý "int _3a" cũng là một tên hợp lệ, dấu gạch dưới đứng đầu khiến chữ số theo sau không còn gây nhập nhằng; chỗ thiếu dấu chấm phẩy ở ý này chỉ là sai sót lúc chép đề, bản thân cái tên không vi phạm quy tắc nào.
Mở trang câu hỏi này →
AIt is a bitwise operator OR
BIt is a logical operator AND
CIt is a bitwise operator AND
DIt is a logical operator OR
Lời giải
Đáp án đúng: "It is a bitwise operator OR". Dấu gạch dọc đơn làm việc ở mức từng bit: nó lấy hai toán hạng nguyên, so từng cặp bit cùng vị trí và cho bit kết quả bằng 1 nếu có ít nhất một bit bằng 1, nên kết quả là một số nguyên chứ không phải một giá trị đúng sai. Chính vì thế nó hay được dùng để bật cờ trong một mặt nạ bit. Ý "It is a logical operator AND" sai vì phép và luận lý phải viết bằng hai dấu và, nó chỉ cho 0 hoặc 1 và còn tính tắt, bỏ hẳn toán hạng bên phải khi bên trái đã sai. Ý "It is a bitwise operator AND" sai vì phép và trên bit viết bằng một dấu và đơn, cho bit 1 chỉ khi cả hai bit đều là 1. Ý "It is a logical operator OR" sai vì phép hoặc luận lý phải viết bằng hai dấu gạch dọc và cũng chỉ trả về 0 hoặc 1.
Mở trang câu hỏi này →
A=
B||
C==
D!=
Lời giải
Đáp án đúng: "=". Dấu bằng đơn là phép gán: nó ghi giá trị của biểu thức bên phải vào ô nhớ bên trái rồi trả về chính giá trị vừa ghi, nên nó thuộc nhóm toán tử gán chứ không so sánh cũng không tổ hợp điều kiện. Đây là cái bẫy kinh điển của C, bởi viết if với một dấu bằng vẫn dịch được mà ý nghĩa đã khác hẳn phép so sánh bằng. Ý "||" sai vì đó là phép hoặc luận lý, nhận hai điều kiện và cho 1 khi có ít nhất một điều kiện đúng. Ý "==" sai vì đó là phép so sánh bằng, trả về 1 hoặc 0 tuỳ hai toán hạng có bằng nhau hay không. Ý "!=" sai vì đó cũng là một phép so sánh, nó kiểm tra hai toán hạng khác nhau và trả về 1 hoặc 0.
Mở trang câu hỏi này →
12What does the following program display?4 lựa chọncó code
Đề bài
#include <stdio.h>

int main()
{
    int x = 1, y = 2, z = 3;

    x = x - --y;
    z = z + ++y;

    printf("%d %d %d", x, y, z);

    return 0;
}
A-1 5 3
B0 2 5
C1 2 4
D1 5 3
Lời giải
Đáp án đúng: "0 2 5". Phép giảm trước --y hạ y từ 2 xuống 1 rồi mới nộp giá trị mới là 1 cho biểu thức, nên x bằng 1 trừ 1 là 0. Ngay sau đó phép tăng trước ++y nâng y từ 1 lên 2 và nộp giá trị 2, nên z bằng 3 cộng 2 là 5, còn y dừng lại ở 2; ba số in ra là 0, 2 và 5. Ý "1 5 3" sai vì y chỉ dao động giữa 1 và 2 nên không thể thành 5, mà x cũng không thể giữ nguyên 1 khi vế phải bị trừ đi một lượng khác 0; đây là khuyết điểm phải công bố của câu này, bộ khoá đi kèm đề chốt đúng bộ số không thể xảy ra ấy. Ý "-1 5 3" sai vì z chắc chắn bị ghi lại ở lệnh thứ hai nên không còn là 3, và giá trị 5 của y vẫn vô căn cứ. Ý "1 2 4" sai vì nó đọc --y và ++y như thể là giảm sau và tăng sau, dùng giá trị cũ của y, trong khi dạng tiền tố luôn thay đổi y trước rồi mới trả giá trị mới.
Mở trang câu hỏi này →
Acondition ? expression1 : expression2
Bcondition ? expression1, expression2
Ccondition : expression1 ? expression2
Dexpression1 : condition ? expression2
Lời giải
Đáp án đúng: "condition ? expression1 : expression2". Toán tử điều kiện là toán tử ba toán hạng duy nhất của C: phần trước dấu hỏi là điều kiện, dấu hỏi mở ra nhánh giá trị dùng khi điều kiện đúng, dấu hai chấm tách sang nhánh giá trị dùng khi điều kiện sai. Cả cụm là một biểu thức có giá trị nên đặt được ngay trong phép gán hay trong đối số của printf, và chỉ đúng một trong hai nhánh được tính. Ý "condition ? expression1, expression2" sai vì thiếu dấu hai chấm, dấu phẩy ở đó lại là toán tử phẩy nên cụm sau dấu hỏi gộp thành một biểu thức duy nhất và không còn nhánh cho trường hợp sai. Ý "condition : expression1 ? expression2" sai vì đảo chỗ hai dấu, dấu hai chấm không được phép đứng ngay sau điều kiện. Ý "expression1 : condition ? expression2" sai vì điều kiện bị đẩy vào giữa, trong khi cú pháp buộc điều kiện phải đứng trước dấu hỏi.
Mở trang câu hỏi này →
14What will the following code output?4 lựa chọncó code
Đề bài
#include <stdio.h>
int main() {
    int a = 7;
    printf("%d", (a << 2) | 1);
    return 0;
}
A28
B29
C15
D30
Lời giải
Đáp án đúng: "29". Biến a bằng 7 có dạng bit là 111. Phép dịch trái hai nhịp đẩy cả ba bit đó sang trái và lấp hai bit 0 vào cuối, thành 11100, tức là 28; đây cũng là lý do dịch trái n nhịp tương đương nhân với 2 lũy thừa n. Tiếp đó phép hoặc trên bit với 1 chỉ chạm vào bit thấp nhất, bit này đang là 0 nên nó được bật lên, cho 11101 là 29. Ý "28" sai vì nó dừng ở kết quả dịch trái, bỏ quên phép hoặc bit đứng sau. Ý "15" sai vì nó ứng với việc chỉ dịch trái một nhịp, ra 14 rồi bật bit thấp nhất thành 15. Ý "30" sai vì muốn ra 30 thì phải bật bit thứ hai tính từ phải, nghĩa là hoặc với 2, còn mặt nạ trong mã là 1; cũng cần nhớ đây là phép hoặc bit chứ không phải phép cộng, nên 28 không tự cộng thêm 2.
Mở trang câu hỏi này →
15What is the output?4 lựa chọncó code
Đề bài
int x = 0, y = 5;
printf("%d", (x && y));
A1
B5
C-1
D0
Lời giải
Đáp án đúng: "0". Phép và luận lý trong C cho ra kết quả thuộc kiểu int và chỉ nhận một trong hai giá trị 0 hoặc 1, nó không trả lại chính toán hạng. Thêm nữa nó tính tắt: thấy toán hạng bên trái bằng 0, nghĩa là sai, thì cả biểu thức đã chắc chắn sai nên y không cần đọc tới. Vì vậy đặc tả %d in ra 0. Ý "1" sai vì 1 chỉ xuất hiện khi cả hai toán hạng đều khác 0. Ý "5" sai vì nó tưởng phép và trả về giá trị của toán hạng cuối, đó là cách làm của một số ngôn ngữ khác chứ không phải của C. Ý "-1" sai vì chuẩn quy định kết quả của các phép luận lý chỉ là 0 hoặc 1, không bao giờ là số âm.
Mở trang câu hỏi này →
ATo determine the value of a variable.
BTo determine the type of a variable.
CTo determine the size (in bytes) occupied by a variable or type.
DTo determine the address of a variable.
Lời giải
Đáp án đúng: "To determine the size (in bytes) occupied by a variable or type.". Toán tử sizeof cho biết số byte mà một đối tượng hay một kiểu chiếm trong bộ nhớ, và nó được tính ngay lúc dịch chứ không phải lúc chạy, vì trình biên dịch đã biết trọn vẹn cách bố trí kiểu. Nhờ nó mà các lời gọi malloc hay realloc viết được theo kiểu dữ liệu, không phải ghi cứng con số byte vốn khác nhau giữa các nền tảng. Ý "To determine the value of a variable." sai vì sizeof không hề đọc giá trị, áp nó lên một biến chưa khởi tạo vẫn ra kết quả đúng. Ý "To determine the type of a variable." sai vì nó trả về một con số, mà hai kiểu khác nhau vẫn có thể cùng kích thước nên con số đó không nhận dạng được kiểu. Ý "To determine the address of a variable." sai vì muốn lấy địa chỉ phải dùng toán tử lấy địa chỉ, sizeof không liên quan tới vị trí của biến.
Mở trang câu hỏi này →
AA constant value stored in memory
BA reference to a memory location
CA function used for binary conversion
DA line number in the code
Lời giải
Đáp án đúng: "A reference to a memory location". Khai báo một biến là yêu cầu trình biên dịch dành ra một vùng nhớ có kích thước đúng theo kiểu rồi gắn cho vùng đó một cái tên; từ đó tên biến trở thành cách gọi tới ô nhớ ấy, đọc tên là đọc nội dung ô, gán cho tên là ghi vào ô. Ý "A constant value stored in memory" sai vì điểm khác biệt của biến so với hằng chính là nội dung có thể thay đổi suốt thời gian chương trình chạy. Ý "A function used for binary conversion" sai vì biến là chỗ chứa dữ liệu, không phải một đoạn mã thực hiện công việc, và nó cũng chẳng làm phép chuyển đổi nào. Ý "A line number in the code" sai vì số dòng chỉ là thông tin của tệp văn bản nguồn, nó không tồn tại trong chương trình đã dịch và không dính gì tới nơi lưu giá trị.
Mở trang câu hỏi này →
18What will this code output?4 lựa chọncó code
Đề bài
int a = 5, b = 10;
printf("%d", !(a > b || b == 10));
A0
B1
C5
D-1
Lời giải
Đáp án đúng: "0". Bên trong cặp ngoặc đơn, phép so sánh a lớn hơn b cho 0 vì 5 không lớn hơn 10, còn phép so sánh b bằng 10 cho 1 vì đúng; phép hoặc luận lý của hai giá trị đó cho 1. Cuối cùng phép phủ định đảo một giá trị khác không thành 0, nên số in ra là 0. Nói gọn thì phủ định một biểu thức đúng luôn cho 0, và kết quả của mọi phép luận lý trong C chỉ nhận hai giá trị 0 hoặc 1. Ý "1" sai vì nó ứng với trường hợp biểu thức trong ngoặc là sai, trong khi nhánh b bằng 10 đã thoả nên cả phép hoặc đã đúng. Ý "5" sai vì không có đường nào để giá trị của a lọt ra kết quả, phép phủ định luôn trả về 0 hoặc 1. Ý "-1" sai vì chuẩn không cho phép phép phủ định sinh ra số âm.
Mở trang câu hỏi này →
Aint number = 10;
Bint number == 10;
Cint number : 10;
Dint number 10;
Lời giải
Đáp án đúng: "int number = 10;". Một khai báo kèm khởi tạo trong C gồm tên kiểu, tên biến, dấu bằng đơn và giá trị, kết thúc bằng dấu chấm phẩy; dấu bằng đơn ở đây là phép gán, nó ghi giá trị vào ô nhớ vừa được dành ra cho biến. Ý "int number == 10;" sai vì hai dấu bằng là phép so sánh, đặt nó vào chỗ khởi tạo khiến trình biên dịch gặp một toán tử không được phép trong khai báo và báo lỗi cú pháp. Ý "int number : 10;" sai vì dấu hai chấm không phải toán tử gán, nó chỉ xuất hiện trong nhãn, trong toán tử điều kiện hoặc trong khai báo trường bit của cấu trúc. Ý "int number 10;" sai vì thiếu hẳn toán tử gán: trình biên dịch đọc xong tên biến lại thấy một hằng số nên không ghép được thành câu lệnh nào.
Mở trang câu hỏi này →
A1 byte
B2 bytes
C4 bytes
D8 bytes
Lời giải
Đáp án đúng: "4 bytes". Kiểu float được hiện thực theo dạng dấu phẩy động độ chính xác đơn của chuẩn IEEE 754, gồm 1 bit dấu, 8 bit số mũ và 23 bit phần định trị, cộng lại đúng 32 bit tức 4 byte; đây là kích thước trên mọi nền tảng phổ thông, và cách kiểm chắc chắn nhất vẫn là in sizeof của kiểu. Ý "1 byte" sai vì đó là kích thước của char, chuẩn quy định sizeof của char luôn bằng 1. Ý "2 bytes" sai vì đó là kích thước thường gặp của short, một kiểu nguyên chứ không phải kiểu thực. Ý "8 bytes" sai vì đó là độ chính xác kép, tức kiểu double; chính vì double rộng gấp đôi nên nó giữ được nhiều chữ số có nghĩa hơn float.
Mở trang câu hỏi này →