PRF192Chưa đoKỳ 1Cơ sở ngành Cập nhật 2 ngày trước

PRF192 - Cơ sở lập trình

PRF192 - Cơ sở lập trình (Programming Fundamentals) là môn học 3 tín chỉ của Đại học FPT, dạy cách giải quyết bài toán thực tế bằng máy tính thông qua ngôn ngữ C, với trọng tâm là thiết kế chương trình hướng hàm, mô-đun hoá, kiểm thử và kỷ luật lập trình. Nội dung môn học bao quát trọn bộ chương trình 60 buổi theo chín chuẩn đầu ra CLO1 đến CLO9. Nội dung gồm: máy tính và phần mềm (khái niệm cơ bản về hệ thống máy tính, các bước phát triển phần mềm, quy trình mã nguồn - biên dịch - liên kết - thực thi, cấu trúc một chương trình C với chỉ thị tiền xử lý #include, hàm main, dấu chấm phẩy kết thúc câu lệnh, chú thích, trình biên dịch và môi trường DevC++); biến, kiểu dữ liệu và biểu thức (khai báo biến và hằng, quy tắc đặt tên định danh, const và #define, các kiểu int, float, double, char và unsigned cùng miền giá trị, nhập xuất bằng scanf và printf với các đặc tả %d %f %c %s, toán tử số học, phép chia nguyên và phép chia lấy dư, toán tử quan hệ, toán tử logic, toán tử trên bit, toán tử gán rút gọn, tăng giảm một đơn vị, trộn kiểu dữ liệu, ép kiểu tường minh và ngầm định, độ ưu tiên và tính kết hợp); cấu trúc điều khiển (rẽ nhánh if, if-else, if lồng nhau, thang else-if, switch-case với break và default; vòng lặp for, while, do-while, break và continue, vòng lặp lồng nhau; phong cách lập trình với thụt lề, đặt tên có nghĩa và chú thích); mô-đun hoá và hàm (mô-đun là gì và vì sao phải mô-đun hoá, tính kết dính cao và ghép nối lỏng, nguyên tắc định nghĩa mô-đun, định nghĩa hàm với kiểu trả về và danh sách tham số, nguyên mẫu hàm, lời gọi hàm, truyền tham số theo giá trị, phân biệt hàm thư viện với hàm tự viết, phạm vi và thời gian sống của biến cục bộ - toàn cục - static, chương trình dạng menu gọi hàm); con trỏ (khái niệm và công dụng, khai báo con trỏ, toán tử lấy địa chỉ và toán tử truy xuất giá trị, số học con trỏ, con trỏ NULL, truyền tham số theo tham chiếu, quan hệ giữa con trỏ và mảng, cấp phát động bằng malloc, calloc, realloc và free, rò rỉ bộ nhớ); thư viện chuẩn C (stdlib.h, time.h, math.h, ctype.h và vào ra có định dạng); mảng và cấu trúc (mảng một chiều, chỉ số bắt đầu từ 0, mảng hai chiều và ma trận, tìm kiếm tuyến tính, sắp xếp chọn, kiểu struct, truy cập thành viên, mảng struct, typedef); chuỗi ký tự (chuỗi là mảng char kết thúc bằng ký tự null, nhập xuất chuỗi, các hàm trong string.h như strlen, strcpy, strcat, strcmp, mảng chuỗi); và tệp tin (tệp văn bản và tệp nhị phân, con trỏ FILE, fopen với các chế độ mở, fclose, truy cập tuần tự và ngẫu nhiên, fprintf, fscanf, fgets, fputs, fread, fwrite, fseek, ftell, feof).

266Câu hỏi
7Bộ đề
9Chủ đề

Câu hỏi của môn

184/266 câuCòn 82
Đề bài
double result;
char op = '*';
int num1 = 5, num2 = 4;
switch (op) {
    case '+': result = num1 + num2; break;
    case '-': result = num1 - num2; break;
    case '*': result = num1 * num2; break;
    case '/': if (num2 != 0) result = num1 / num2; break;
    default: printf("Invalid Operator");
}
printf("%d", result);
A20
B9
C1.25
D0
Lời giải
Đáp án đúng: "20". Biến op mang hằng ký tự dấu nhân, nên switch rẽ vào đúng nhãn khớp với ký tự đó và thực hiện result bằng num1 nhân num2, tức 5 nhân 4 bằng 20, rồi break thoát switch. Cần công bố một khuyết điểm của đề: result khai báo kiểu double nhưng lại in bằng đặc tả số nguyên, đây là sai khớp định dạng nên con số hiện trên màn hình không được bảo đảm; câu hỏi chỉ xét giá trị mà switch tính ra, và giá trị đó là 20. Lựa chọn "9" là kết quả của nhánh cộng, chỉ chạy nếu op mang dấu cộng. Lựa chọn "1.25" là 5 chia 4 theo nghĩa thực, nhưng nhánh chia không được chọn, và hơn nữa num1 chia num2 giữa hai số nguyên sẽ cho 1 chứ không phải 1.25. Lựa chọn "0" ứng với trường hợp result chưa bao giờ được gán, tức op không khớp nhãn nào và chỉ nhánh mặc định chạy.
Mở trang câu hỏi này →
AIt can only be used with integer or character type expressions.
BIt can be used with any data type.
CIt can only be used in functions.
DIt can only have one case statement inside.
Lời giải
Đáp án đúng: "It can only be used with integer or character type expressions.". Chuẩn C đòi biểu thức điều khiển của switch phải có kiểu nguyên, và mỗi nhãn case phải là hằng nguyên tính được lúc dịch; ký tự thoả yêu cầu này vì char được nâng lên int và hằng ký tự chính là một số nguyên. Lý do nằm ở cách dịch: trình dịch cần so sánh bằng chính xác hoặc dựng bảng nhảy, điều không làm được với số thực hay chuỗi. Lựa chọn "It can be used with any data type." sai vì float, double hay mảng ký tự đều bị từ chối, muốn phân nhánh theo chúng phải dùng chuỗi if else. Lựa chọn "It can only be used in functions." không nói lên điều gì riêng của switch, bởi mọi câu lệnh thực thi trong C đều nằm trong thân hàm. Lựa chọn "It can only have one case statement inside." sai vì switch mang bao nhiêu nhãn case cũng được, đó chính là lý do người ta chọn nó.
Mở trang câu hỏi này →
Đề bài
#include <stdio.h>
int  main()
{
        int x=7;
        for(;x>3;)
            printf("Yes");
            x--;
    return 0;
}
AInfinite loop
BCompile time error
CYesYesYesYes
DYes
Lời giải
Đáp án đúng: "Infinite loop". Phạm vi của thân vòng lặp do ngoặc nhọn quyết định, không do thụt lề: for ở đây không mở ngoặc nhọn nên thân nó chỉ ôm đúng một lệnh là printf, còn x-- nằm ngoài vòng lặp dù được thụt vào cho giống thân. Vì vậy x giữ nguyên giá trị 7, điều kiện x lớn hơn 3 mãi đúng, chương trình in Yes không ngừng và x-- không bao giờ tới lượt chạy. Lựa chọn "Compile time error" sai vì for cho phép bỏ trống cả phần khởi tạo và phần cập nhật, chỉ cần giữ hai dấu chấm phẩy, nên mã này dịch được. Lựa chọn "YesYesYesYes" là kết quả nếu x-- được đưa vào trong ngoặc nhọn cùng printf, khi đó x giảm từ 7 xuống 3 và in bốn lần. Lựa chọn "Yes" đòi vòng lặp chỉ chạy một lượt, điều chỉ xảy ra nếu có break hoặc nếu điều kiện hỏng ngay sau lượt đầu.
Mở trang câu hỏi này →
AThe loop is skipped entirely.
BThe loop executes indefinitely.
CThe loop executes once and then terminates.
DAn error occurs.
Lời giải
Đáp án đúng: "The loop is skipped entirely.". while là vòng lặp kiểm tra trước: điều kiện được xét trước khi thân chạy lần nào, nên nếu nó sai ngay từ đầu thì thân không chạy lượt nào và chương trình đi thẳng tới lệnh sau vòng lặp. Đây chính là điểm phân biệt với do while, loại luôn chạy thân ít nhất một lần vì điều kiện bị xét ở cuối. Lựa chọn "The loop executes indefinitely." mô tả tình huống ngược lại, khi điều kiện luôn đúng vì thân không làm biến điều kiện thay đổi. Lựa chọn "The loop executes once and then terminates." đúng với do while chứ không đúng với while. Lựa chọn "An error occurs." sai vì điều kiện sai ngay từ đầu là tình huống hoàn toàn hợp lệ và thường dùng, chẳng hạn vòng lặp đọc dữ liệu khi không còn dữ liệu nào để đọc.
Mở trang câu hỏi này →
AConverts a string to an integer
BConverts an integer to a string
CCopy a string
DConverts a string to a number
Lời giải
Đáp án đúng: "Converts a string to an integer". Tên hàm atoi viết tắt cho cụm ASCII to integer: nó đọc chuỗi ký tự số, bỏ khoảng trắng đầu, nhận dấu rồi dựng ra một số nguyên. Cần công bố một khuyết điểm của đề: nguyên mẫu thật trong stdlib.h là int atoi(const char *str) chứ không phải void, vì nếu trả về void thì hàm không có cách nào đưa số nguyên ra cho nơi gọi. Lựa chọn "Converts an integer to a string" là chiều ngược lại, việc của sprintf. Lựa chọn "Copy a string" là việc của strcpy, không liên quan tới chuyển kiểu. Lựa chọn "Converts a string to a number" nghe gần đúng nhưng không nêu được kiểu đích: họ hàm này còn có atof cho số thực, còn atoi riêng ở chỗ cho ra số nguyên và cắt bỏ phần thập phân, nên cách diễn đạt chung chung ấy không phân biệt được hai hàm.
Mở trang câu hỏi này →
Amath.h
Bstdlib.h
Ctime.h
Dctype.h
Lời giải
Đáp án đúng: "math.h". Các hàm toán học như sqrt, pow, sin, cos, fabs, floor cùng những hằng liên quan được khai báo trong math.h, nên muốn gọi chúng phải nạp tệp tiêu đề này; thiếu nó thì trình dịch không biết hàm trả về double và dễ sinh kết quả sai, trên một số hệ còn phải nối thêm thư viện toán khi liên kết. Lựa chọn "stdlib.h" chứa tiện ích chung như malloc, free, atoi, rand và exit, không chứa hàm lượng giác hay căn bậc hai. Lựa chọn "time.h" lo thời gian và ngày tháng với time, clock, localtime. Lựa chọn "ctype.h" lo phân loại ký tự và đổi hoa thường với isdigit, isalpha, toupper, nó không làm tính toán số học.
Mở trang câu hỏi này →
Afflush()
Bclearbuffer()
Cclear input()
Dclrscr()
Lời giải
Đáp án đúng: "fflush()". Trong bốn tên được nêu chỉ fflush là hàm thật của thư viện chuẩn, khai báo trong stdio.h, dùng để đẩy sạch vùng đệm của một dòng vào ra; thói quen quen thuộc khi dạy nhập liệu là gọi nó để bỏ phần còn sót trong vùng đệm bàn phím sau scanf, chẳng hạn ký tự xuống dòng còn lại làm getchar kế tiếp nhận sai. Cần nói rõ: chuẩn chỉ định nghĩa fflush cho dòng xuất, dùng nó cho dòng nhập là hành vi không xác định dù nhiều trình dịch vẫn làm đúng ý người viết. Lựa chọn "clearbuffer()" không tồn tại trong thư viện chuẩn. Lựa chọn "clear input()" thậm chí không phải một tên hợp lệ vì có khoảng trắng ở giữa. Lựa chọn "clrscr()" thuộc conio.h phi chuẩn và nhiệm vụ của nó là xoá màn hình, không dính gì tới vùng đệm bàn phím.
Mở trang câu hỏi này →
Đề bài
#include <stdio.h>

int f(int a, int b, int c) {
    int t = 2*(a+b-c)/5;
    return t;
}

int main() {
    int x = 5, y = 6, z = 7;
    int t = 3*f(y,x,z);
    printf("%d", t);
    return 0;
}
A3
B1
C8
D2
Lời giải
Đáp án đúng: "3". Thứ tự đối số là chỗ cần bám: lời gọi f(y,x,z) gán a bằng 6, b bằng 5, c bằng 7. Trong hàm, a cộng b trừ c cho 4, nhân 2 thành 8, rồi 8 chia 5 là phép chia giữa hai số nguyên nên C cắt phần thập phân cho ra 1, không làm tròn lên 2. Hàm trả về 1, main nhân 3 và in 3. Lựa chọn "1" là giá trị hàm trả về, bỏ quên phép nhân 3 ở main. Lựa chọn "8" là tử số 2 nhân với 4, tức dừng lại trước khi chia cho 5. Lựa chọn "2" ứng với cách hiểu 8 chia 5 bằng 1.6 rồi làm tròn thành 2, nhưng chia nguyên trong C luôn cắt về phía 0, và ngay cả khi làm tròn thì kết quả cuối vẫn còn phải nhân 3 nữa.
Mở trang câu hỏi này →
Avoid printSum(int* a, int b);
Bint printSum(int* a, int b);
Cint printSum(int a, b);
Dint* printSum(int* a, int b);
Lời giải

Đáp án đúng: "int printSum(int a, b);". Trong nguyên mẫu hàm, mỗi tham số phải tự mang kiểu của mình; không có chuyện viết một kiểu rồi dùng chung cho các tên phía sau như khi khai báo biến. Ở dòng này b không có kiểu, trình dịch cũng không được suy ra int ngầm trong nguyên mẫu, nên nó báo lỗi; muốn đúng phải viết int printSum(int a, int b). Dòng "void printSum(int* a, int b); " hợp lệ: hàm không trả về gì, nhận một con trỏ int và một int. Dòng "int printSum(int* a, int b);" cũng hợp lệ và là cách thường dùng khi muốn hàm sửa được biến gốc qua con trỏ rồi vẫn trả về mã kết quả. Dòng "int* printSum(int* a, int b);" hợp lệ nữa, chỉ khác ở chỗ hàm trả về một con trỏ int; dấu sao gắn vào kiểu trả về là cú pháp bình thường.

Mở trang câu hỏi này →
APass by value
BPass by reference
CPass by address
DPass by pointer
Lời giải
Đáp án đúng: "Pass by value". C chỉ có một cơ chế truyền tham số duy nhất là truyền theo giá trị: đối số được sao vào tham số hình thức, nên hàm làm việc trên bản sao và mọi phép gán bên trong không chạm tới biến gốc của nơi gọi. Lựa chọn "Pass by reference" không tồn tại trong C vì ngôn ngữ này không có kiểu tham chiếu; kiểu đó thuộc C++ và nó cho hàm sửa trực tiếp biến gốc, trái với yêu cầu của câu hỏi. Lựa chọn "Pass by address" là cách người ta mô phỏng hiệu ứng tham chiếu bằng cách truyền địa chỉ, khi đó hàm sửa được biến gốc qua phép lấy nội dung con trỏ, đúng điều đề muốn tránh. Lựa chọn "Pass by pointer" là tên gọi khác của cùng kỹ thuật ấy: bản thân con trỏ vẫn được sao, nhưng bản sao trỏ tới cùng ô nhớ nên biến gốc vẫn bị thay đổi.
Mở trang câu hỏi này →
Đề bài
int a = 0;
char line1[] = "Hi";
char line2[] = "Hello";
a = strcmp(line1, line2);
A0
BA positive value
CA negative value
DNAN
Lời giải
Đáp án đúng: "A positive value". Hàm strcmp so từng cặp ký tự theo mã của chúng và trả về chênh lệch tại vị trí đầu tiên khác nhau. Hai chuỗi cùng mở đầu bằng một chữ hoa giống nhau, sang vị trí thứ hai thì chuỗi ngắn có ký tự i mã 105 còn chuỗi dài có ký tự e mã 101; vì 105 lớn hơn 101 nên hàm cho ra số dương, nghĩa là chuỗi thứ nhất đứng sau theo thứ tự từ điển. Chú ý việc so sánh dừng ngay tại cặp lệch đầu tiên, độ dài chuỗi không quyết định. Lựa chọn "0" chỉ đúng khi hai chuỗi giống nhau hoàn toàn tới ký tự kết thúc. Lựa chọn "A negative value" sẽ đúng nếu ký tự lệch đầu tiên của chuỗi thứ nhất nhỏ hơn, tức khi đổi thứ tự hai đối số. Lựa chọn "NAN" không có nghĩa ở đây vì strcmp trả về int, không phải số thực, nên không bao giờ sinh giá trị không phải số.
Mở trang câu hỏi này →
Arand(time(0));
Bsrand(time(NULL));
Csrand();
Drandomize();
Lời giải
Đáp án đúng: "srand(time(NULL));". Hàm rand sinh dãy giả ngẫu nhiên hoàn toàn xác định từ một hạt giống; không gieo hạt thì chương trình coi như hạt bằng 1 và mỗi lần chạy lại cho đúng dãy cũ. Gọi srand với time(NULL), tức số giây tính từ mốc thời gian hệ thống, làm hạt đổi theo từng lần chạy nên dãy số cũng đổi. Chỉ nên gieo một lần ở đầu chương trình, gieo lại trong vòng lặp sẽ phản tác dụng vì trong cùng một giây hạt không đổi. Lựa chọn "rand(time(0));" sai vì rand không nhận đối số, nhiệm vụ gieo hạt thuộc srand. Lựa chọn "srand();" thiếu đối số bắt buộc nên không dịch được, và nếu bỏ hẳn lời gọi thì lại rơi vào hạt mặc định. Lựa chọn "randomize();" là hàm riêng của Borland, không có trong thư viện chuẩn nên mã dùng nó không dịch được ở nơi khác.
Mở trang câu hỏi này →
177What is an array in C programming?4 lựa chọn
AA collection of elements of the same data type stored in contiguous memory locations.
BA single variable that holds multiple values of different data types.
CA pointer to a single element in memory
DA function that performs mathematical calculations.
Lời giải
Đáp án đúng: "A collection of elements of the same data type stored in contiguous memory locations.". Mảng trong C là một dãy phần tử cùng kiểu nằm liền kề trong bộ nhớ; chính tính liền kề và cùng kiểu cho phép tính địa chỉ phần tử thứ i chỉ bằng địa chỉ đầu cộng i lần kích thước kiểu, nhờ vậy truy cập theo chỉ số nhanh như nhau ở mọi vị trí và số học con trỏ trên mảng mới chạy được. Lựa chọn "A single variable that holds multiple values of different data types." mô tả kiểu cấu trúc, nơi các thành phần được phép khác kiểu. Lựa chọn "A pointer to a single element in memory" lẫn mảng với con trỏ: tên mảng tự suy biến thành địa chỉ phần tử đầu khi dùng trong biểu thức, nhưng bản thân mảng là vùng dữ liệu chứa nhiều phần tử chứ không phải một biến con trỏ. Lựa chọn "A function that performs mathematical calculations." nói về hàm, không phải cấu trúc dữ liệu.
Mở trang câu hỏi này →
Đề bài
#include<stdio.h>
void increment(int *ptr) {
    (*ptr)++;
}
int main(){
        int x=1005;
        increment(&x);
        printf("%d ",x);
}
A1006
B1005
C0
D1007
Lời giải
Đáp án đúng: "1006". Hàm main truyền &x, tức địa chỉ của x, nên tham số ptr trỏ đúng vào ô nhớ của x. Trong hàm, (*ptr)++ lấy nội dung tại ô đó rồi tăng chính ô đó lên một, vì vậy x ở main thành 1006 trước khi printf chạy; đây là cách duy nhất để một hàm trong C sửa được biến của nơi gọi. Cặp ngoặc quanh phép lấy nội dung là chi tiết quan trọng: nếu viết thiếu nó thì phép tăng áp lên bản thân con trỏ chứ không lên giá trị được trỏ tới. Lựa chọn "1005" là giá trị cũ, chỉ đúng nếu hàm nhận một bản sao int và tăng bản sao đó. Lựa chọn "0" không ứng với bước nào vì x được khởi tạo 1005 và chỉ chịu một phép tăng. Lựa chọn "1007" đòi hai lần tăng, trong khi hàm chỉ được gọi một lần và thân hàm chỉ có một phép tăng.
Mở trang câu hỏi này →
179What is the output of the following code?4 lựa chọncó code
Đề bài
int a[5] = {1, 2, 3, 4, 5};
printf("%d", a);
AAddress of the first element of array a
BCompiler error
CGarbage value
DError: mismatched format specifier in printf
Lời giải
Đáp án đúng: "Address of the first element of array a". Tên mảng dùng trong biểu thức tự suy biến thành con trỏ tới phần tử đầu, nên giá trị thực sự được đẩy cho printf là địa chỉ của phần tử có chỉ số 0. Phải nói thẳng một khuyết điểm của mã: đặc tả số nguyên chờ một int mà lại nhận con trỏ, đây là sai khớp định dạng và trên máy 64 bit là hành vi không xác định; thứ nhìn thấy trên màn hình chính là địa chỉ đó bị đọc lại như số nguyên hệ mười. Lựa chọn "Compiler error" sai vì printf nhận số đối số thay đổi nên kiểu không bị kiểm ở mức ngăn dịch, nhiều lắm là một cảnh báo. Lựa chọn "Garbage value" không chính xác: con số in ra là một địa chỉ có thật của vùng mảng, nó chỉ khác nhau giữa các lần chạy chứ không phải rác. Lựa chọn "Error: mismatched format specifier in printf" cũng sai vì ngôn ngữ không bắt buộc chẩn đoán cho sai khớp này, chương trình vẫn dịch và vẫn chạy.
Mở trang câu hỏi này →
Đề bài
int a[] = {1, 2, 3, 4, 5}, i;
float sum = 0;
for (i = 0; i < 4; i++)  {
    sum = sum + a[i]/a[i+1];
}
printf("%.2f", sum);
A0.00
B2.72
C2.80
DRuntime Error
Lời giải
Đáp án đúng: "0.00". Mỗi hạng tử là phép chia giữa hai phần tử int, nên kết quả bị cắt về số nguyên ngay trước khi được cộng vào sum; việc sum có kiểu float không cứu được gì vì sự cắt đã xảy ra rồi. Bốn lượt cho 1 chia 2 bằng 0, 2 chia 3 bằng 0, 3 chia 4 bằng 0 và 4 chia 5 bằng 0, nên sum vẫn là 0 và in ra 0.00. Muốn có chia thực phải ép một toán hạng sang float trước khi chia. Lựa chọn "2.72" chính là tổng khi chia thực, tức 0.5 cộng 0.67 cộng 0.75 cộng 0.8, nên nó giả định sai rằng kiểu của biến nhận kết quả quyết định kiểu của phép chia. Lựa chọn "2.80" không khớp với tổng nào ở đây, dù tính theo chia nguyên hay chia thực. Lựa chọn "Runtime Error" lo nhầm về vượt biên, nhưng i chỉ chạy tới 3 nên chỉ số lớn nhất được đọc là 4, vẫn nằm trong năm phần tử.
Mở trang câu hỏi này →
181What does the following code print?6 lựa chọncó code
Đề bài
#include <stdio.h>
void swap(int a, int *b) {
    int temp = a;
    a = *b;
    *b = temp;
}
int main() {
    int x = 5;
    int y = 10;
    swap(x, y);
    printf("x = %d, y = %d\n", x, y);
    return 0;
}
ARuntime error.
BCompiler error.
Cx = 5, y = 10
Dx = 10, y = 5
Ex = 10, y = 10
Fx = 5, y = 5
Lời giải
Đáp án đúng: "Compiler error.". Tham số thứ hai của swap khai báo là con trỏ int, nhưng lời gọi swap(x, y) lại đưa vào y là một int. C không chuyển ngầm int sang con trỏ, đó là vi phạm ràng buộc kiểu khi đã có nguyên mẫu, nên trình dịch báo lỗi và không có chương trình nào được sinh ra để chạy. Lựa chọn "Runtime error." sai vì sự cố xảy ra lúc dịch, chưa tới lượt thực thi. Lựa chọn "x = 5, y = 10" là kết quả nếu mã dịch được và hàm không chạm tới hai biến, nhưng ở đây không dòng nào được in. Lựa chọn "x = 10, y = 5" giả định một phép đổi chỗ hoàn chỉnh, điều thân hàm này không làm nổi vì tham số thứ nhất chỉ là bản sao của x. Lựa chọn "x = 10, y = 10" đòi x nhận giá trị của y, trong khi phép gán bên trong chỉ sửa bản sao. Lựa chọn "x = 5, y = 5" đòi y nhận 5 qua con trỏ, nhưng muốn vậy phải truyền địa chỉ của y chứ không phải giá trị của nó.
Mở trang câu hỏi này →
182What will the following program output?4 lựa chọncó code
Đề bài
#include <stdio.h>
#define ANSWER 42

int main() {
    printf("%d", ANSWER);
    return 0;
}
A42
BANSWER
CCompilation Error
DNo Output
Lời giải
Đáp án đúng: "42". Chỉ thị define thuộc bộ tiền xử lý: trước khi trình dịch thấy mã, bộ tiền xử lý thay mọi lần xuất hiện của tên hằng trong luồng mã nguồn bằng dãy ký tự 42. Vì vậy lệnh in thực chất nhận một hằng nguyên 42 và màn hình hiện 42. Hằng kiểu này không phải biến, không chiếm ô nhớ, không có kiểu riêng; nó chỉ là phép thay thế văn bản. Lựa chọn "ANSWER" sẽ đúng nếu tên hằng nằm bên trong một hằng chuỗi, vì bộ tiền xử lý không thay thế bên trong chuỗi; ở đây tên nằm ngoài chuỗi, tại vị trí đối số, nên nó bị thay. Lựa chọn "Compilation Error" sai vì sau khi thay thế, đặc tả số nguyên khớp đúng với một hằng nguyên. Lựa chọn "No Output" sai vì printf vẫn được gọi và luôn xuất ra dòng chuẩn.
Mở trang câu hỏi này →
APointer
BAddress
CInteger
DByte
Lời giải
Đáp án đúng: "Pointer". Biến dùng để chứa địa chỉ của một biến khác được gọi là con trỏ; nó có kiểu riêng gắn với kiểu dữ liệu được trỏ tới, nhờ đó phép lấy nội dung biết đọc bao nhiêu byte và số học con trỏ biết bước nhảy dài bao nhiêu. Chính cơ chế này giúp hàm trong C sửa được biến của nơi gọi và giúp cấp phát động hoạt động. Lựa chọn "Address" là tên của giá trị được chứa, không phải tên của biến chứa nó; nói cách khác địa chỉ là nội dung, con trỏ là cái hộp. Lựa chọn "Integer" là kiểu số nguyên thường; dù địa chỉ trông như một số thì việc gán số nguyên cho con trỏ vẫn đòi ép kiểu và không an toàn. Lựa chọn "Byte" là đơn vị đo dung lượng bộ nhớ, không phải một loại biến của ngôn ngữ.
Mở trang câu hỏi này →
184Assume we have a snippet code in C:4 lựa chọncó code
Đề bài
int main() {
    int *p = NULL;
    printf("%d",p);
    getchar();
    return 0;
}

The output will be:

A0
B1
C10
D100
Lời giải
Đáp án đúng: "0". Hằng con trỏ rỗng trong thực tế được mọi trình dịch phổ thông hiện thực bằng giá trị số 0, nên p mang giá trị 0 và lệnh in cho ra 0. Cần nói rõ phần khuyết của mã: đặc tả số nguyên chờ một int mà nhận con trỏ, đây là sai khớp định dạng và là hành vi không xác định theo chuẩn; nó chỉ cho kết quả như mong đợi vì giá trị bên trong con trỏ rỗng đúng là 0. Cách viết đúng là dùng đặc tả con trỏ và ép sang con trỏ vô kiểu. Lựa chọn "1" không ứng với gì ở đây vì không có phép tăng nào trên p. Lựa chọn "10" sẽ đúng nếu p được gán giá trị 10, nhưng mã chỉ gán hằng con trỏ rỗng. Lựa chọn "100" cũng vậy, không có phép tính nào trong mã sinh ra con số đó.
Mở trang câu hỏi này →