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

Câu hỏi: PRF192 - Phần 5: Con trỏ

41 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/41 câuCòn 21
1What will be the output of the following C code?4 lựa chọncó code
Đề bài
#include <stdio.h>
void main()
{
    int *ptr, a = 10;
    ptr = &a;
    *ptr += 1;
    printf("%d,%d\n", *ptr, a);
}
A10,10
B10,11
C11,10
D11,11
Lời giải
Đáp án đúng: "11,11". Lệnh ptr = &a làm ptr giữ địa chỉ ô nhớ của a, nên *ptr và a là hai cách gọi cùng một chỗ chứ không phải hai bản sao; *ptr += 1 cộng 1 vào chính ô đó nên a thành 11, và khi in thì cả *ptr lẫn a đều đọc ra 11. Bản chất là bí danh: con trỏ không chứa giá trị, nó chỉ chứa địa chỉ. "10,10" sai vì phép cộng đã thực sự ghi vào bộ nhớ, giá trị không còn là 10. "10,11" sai vì *ptr không thể đọc ra giá trị cũ khi ô nhớ đã đổi. "11,10" sai vì a không phải bản sao riêng, nó chính là ô nhớ mà ptr trỏ tới, nên không thể giữ 10 trong khi *ptr đã là 11.
Mở trang câu hỏi này →
Đề bài
#include <stdio.h>
#include <conio.h>
int main() {
    int n = 267, *pn = &n;
    char* pc = pn;
    *pc = 0;
    printf("n = %d", n);
    return 0;
}
An = 0
Bn = 267
Cn = 256
Derror
Lời giải
Đáp án đúng: "n = 256". n bằng 267, viết ở hệ mười sáu là 0x010B, tức một byte chứa 0x0B là 11 và byte cao hơn chứa 0x01 ứng với 256. Con trỏ pc giữ cùng địa chỉ của n nhưng mang kiểu con trỏ ký tự, nên *pc = 0 chỉ ghi 0 vào đúng một byte, byte nằm ở địa chỉ thấp nhất; trên máy lưu byte nhỏ trước, byte đó chính là 0x0B, vì vậy n còn lại 0x0100 là 256. "n = 0" sai vì một phép gán qua con trỏ ký tự chỉ xoá một byte, các byte còn lại của int không bị chạm. "n = 267" sai vì phép ghi đã thực sự thay đổi bộ nhớ. "error" sai vì gán con trỏ int cho con trỏ ký tự chỉ khiến trình biên dịch cảnh báo kiểu không khớp, mã vẫn dịch và chạy ra kết quả.
Mở trang câu hỏi này →
3What will be the output of the C program?4 lựa chọncó code
Đề bài
int arr[5] = { 2, 3, 5, 4, 7 };
int *ptr = (&arr + 1);
printf("%d %d\n", *(arr + 1), *(ptr - 1));
A2 3
B3 2
C3 7
D2 6356728
Lời giải
Đáp án đúng: "3 7". Tên mảng arr khi dùng trong biểu thức suy biến thành con trỏ tới phần tử đầu, nên *(arr + 1) chính là arr[1], bằng 3. Nhưng &arr lại mang kiểu con trỏ tới cả mảng năm int, nên &arr + 1 nhảy qua trọn mảng và trỏ vào ô ngay sau arr[4]; gán vào int *ptr rồi ptr - 1 lùi đúng một ô int nên về arr[4], bằng 7. Chương trình in 3 7. Cần công bố khuyết điểm: bản khoá in kèm ghi 3 2, giá trị đó chỉ ra được nếu hiểu &arr + 1 nhảy một phần tử như arr + 1, khi đó ptr - 1 mới về arr[0], nên "3 2" sai. "2 3" lấy arr[0] cho vế đầu, nhưng vế đầu là arr[1]. "2 6356728" giả định đọc phải rác ngoài mảng, trong khi ptr - 1 vẫn trỏ vào đúng phần tử cuối của arr.
Mở trang câu hỏi này →
Đề bài
int main()
{
        int i = 101;
            int *p = &i;
            printf("%d\n", *p++);
    return 0;
}
A101
B102
C0
DAddress of i
Lời giải
Đáp án đúng: "101". Trong biểu thức *p++, toán tử tăng hậu tố gắn với p chứ không với *p, và nó trả về giá trị con trỏ trước khi tăng, nên phép lấy nội dung làm việc trên địa chỉ cũ, tức đọc i và in 101; chỉ sau lệnh đó p mới trỏ ra ô kế tiếp, điều này vô hại vì p không được dùng nữa. "102" là kết quả nếu tăng chính giá trị được trỏ, tức viết (*p)++ hoặc ++*p; ở đây phép tăng chạm vào con trỏ, không chạm vào i. "0" không có cơ sở nào vì ô nhớ của i chứa 101 và không bị ghi lại. "Address of i" sai vì biểu thức *p đã lấy nội dung chứ không phải địa chỉ, hơn nữa muốn in địa chỉ thì phải dùng p với định dạng %p.
Mở trang câu hỏi này →
Afree()
Bmalloc()
Ccalloc()
Drealloc()
Lời giải
Đáp án đúng: "free()". Bộ nhớ cấp phát động nằm trên vùng heap và chỉ được trả lại khi chương trình gọi free với chính con trỏ mà hàm cấp phát đã trả về; không gọi thì vùng đó vẫn bị giữ tới khi tiến trình kết thúc, đó là rò rỉ bộ nhớ. "malloc()" làm việc ngược lại, nó xin một khối byte rồi trả về con trỏ, nội dung chưa được đặt giá trị. "calloc()" cũng là hàm xin bộ nhớ, khác malloc ở chỗ nhận số phần tử cùng kích thước mỗi phần tử và xoá vùng nhớ về 0. "realloc()" thay đổi kích thước một khối đã có, nó có thể chuyển khối sang chỗ khác và trả con trỏ mới, nhưng không phải hàm dùng để giải phóng.
Mở trang câu hỏi này →
Đề bài
#include <stdio.h>
int main() {
    int a[] = {1,2,3,4,5,6};
    int* p = a;
    p += 3;
    printf("%d, %d",*(a+3), *(p++));
    return 0;
}
A3 3
B4 5
C4 4
D3 4
Lời giải
Đáp án đúng: "4 4". Mảng a chứa 1,2,3,4,5,6 nên a[3] bằng 4; biểu thức *(a+3) đúng là a[3], in ra 4. Con trỏ p ban đầu trỏ a[0], lệnh p += 3 đưa p tới a[3]; trong *(p++), phép tăng hậu tố trả về giá trị con trỏ trước khi tăng nên phép lấy nội dung đọc đúng a[3], cũng ra 4, chỉ sau đó p mới nhích sang a[4] và không còn được dùng nữa. Vì vậy chương trình in 4 4. "3 3" nhầm chỉ số với giá trị: cộng 3 vào con trỏ cho địa chỉ của phần tử thứ tư, không cho số 3. "4 5" là kết quả nếu phép tăng trả về giá trị sau khi tăng, tức viết *(++p); dạng hậu tố thì không như vậy. "3 4" đọc sai vế đầu thành a[2], mà hai vế đều trỏ vào cùng một phần tử nên hai số in ra phải giống nhau.
Mở trang câu hỏi này →
Đề bài
int main()
{
    int i = 1;
    int *p = &i;
    int **k = &p;
    i+=2;
    printf("%d%d%d", *p, **k, *(*k));
    getchar();
    return 0;
}
A333
B111
C222
DCompile error
Lời giải
Đáp án đúng: "333". Biến i ban đầu bằng 1, p giữ địa chỉ của i, còn k giữ địa chỉ của p nên k là con trỏ hai cấp. Lệnh i+=2 nâng i lên 3 ngay trong ô nhớ của i. Vì p và k không sao chép giá trị mà chỉ ghi lại đường đi tới ô nhớ đó, mọi lần truy xuất về sau đều đọc ra giá trị mới nhất: *p lấy nội dung ô của i là 3, **k đi hai chặng từ k sang p rồi sang i cũng ra 3, và *(*k) chỉ là cách viết tường minh của **k nên cũng ra 3. Chuỗi định dạng có ba đặc tả %d liền nhau không chen dấu cách nên ba số in sát nhau thành 333. Ý "111" sai vì nó ứng với việc bỏ qua lệnh i+=2, hoặc tưởng con trỏ chụp lại giá trị ngay lúc được gán. Ý "222" sai vì không có phép tính nào trong chương trình sinh ra giá trị 2. Ý "Compile error" sai vì khai báo con trỏ hai cấp và phép lấy nội dung hai lần đều hợp lệ.
Mở trang câu hỏi này →
8Assume we have the following codes:4 lựa chọncó code
Đề bài
double d=9;
double *p = &d;

Suppose that a double occupies the memory block of 8 bytes, and the address of d is 1200. What is the result of the following expression: p + 8?

A1264
B1200
C1208
D1209
Lời giải
Đáp án đúng: "1264". Phép cộng trên con trỏ trong C được tính theo đơn vị phần tử, không theo byte: p có kiểu con trỏ tới double nên p cộng 8 nghĩa là nhảy qua 8 ô double, tức là dịch 8 nhân 8 bằng 64 byte kể từ địa chỉ 1200, cho ra 1264. Nhờ đúng quy ước này mà cách viết p cộng i luôn trỏ tới phần tử thứ i mà người viết không phải nhân tay với kích thước kiểu. Ý "1200" sai vì đó là giá trị của chính p khi chưa cộng gì. Ý "1208" sai vì 1208 là kết quả của p cộng 1, nhảy đúng một ô double. Ý "1209" sai vì nó coi con trỏ như một số nguyên thường rồi cộng thẳng 9 vào, vừa nhầm bước nhảy vừa nhầm cả số hạng; địa chỉ đó còn rơi vào giữa một ô double nên không phải chỗ bắt đầu của phần tử nào.
Mở trang câu hỏi này →
9What does the following program print?4 lựa chọncó code
Đề bài
#include <stdio.h>

int main() {
    int a = 4, *b = &a;
    a--;
    *b=*b-1;
    printf("%d %d", a, *b);
    return 0;
}
A2 2
B2 1
C3 1
D3 3
Lời giải
Đáp án đúng: "2 2". Con trỏ b được gán địa chỉ của a nên từ đó a và *b là hai tên gọi của cùng một ô nhớ. Lệnh a-- hạ ô đó từ 4 xuống 3, rồi *b = *b - 1 đọc chính ô đó được 3, trừ đi 1 và ghi lại 2; khi printf chạy, cả a lẫn *b đều lấy từ ô duy nhất ấy nên hai số in ra buộc phải giống nhau. Ý "3 1" sai vì nó coi a và *b là hai biến riêng, mỗi biến bị giảm đúng một lần; đây cũng là khuyết điểm phải công bố của câu này, bộ khoá đi kèm đề ghi đúng cặp số ấy trong khi mã nguồn không thể sinh ra hai giá trị khác nhau. Ý "2 1" sai vì nó cộng cả hai lần giảm vào a nhưng chỉ tính một lần cho *b, điều không thể xảy ra với hai tên của cùng một ô nhớ. Ý "3 3" sai vì nó bỏ quên một trong hai lệnh giảm, chỉ hạ giá trị từ 4 xuống 3.
Mở trang câu hỏi này →
Aptr = realloc( ptr, 5 * sizeof(int) );
Brealloc( ptr, 5 * sizeof(int) );
Cptr += malloc( 5 * sizeof( int ) );
Drealloc( ptr, 20);
Eptr = realloc( ptr, 20);
Lời giải
Đáp án đúng: "ptr += malloc( 5 * sizeof( int ) );". Lệnh này sai ngay từ lúc dịch vì phép cộng trên con trỏ chỉ chấp nhận một bên là con trỏ và bên kia là số nguyên; ở đây cả hai bên đều là con trỏ, malloc trả về một con trỏ void, nên biểu thức không có nghĩa và trình biên dịch báo toán hạng không hợp lệ. Ý tưởng ấy còn sai về bản chất: muốn nới một vùng nhớ đã cấp thì phải gọi realloc, chứ không phải dịch con trỏ đi đâu đó. Ý "ptr = realloc( ptr, 5 * sizeof(int) );" là cách viết đúng chuẩn, dịch được và chạy đúng. Ý "realloc( ptr, 5 * sizeof(int) );" vẫn dịch được, chỉ bỏ mất con trỏ mới trả về nên tiềm ẩn rò rỉ và con trỏ treo, nhưng đề hỏi lệnh gây lỗi nên nó không phải lựa chọn. Ý "realloc( ptr, 20);" cũng dịch được, chỉ là ghi cứng số byte. Ý "ptr = realloc( ptr, 20);" dịch được và chạy đúng khi int chiếm 4 byte.
Mở trang câu hỏi này →
11What is the output of the following code snippet?4 lựa chọncó code
Đề bài
void main(){
    int x = 4;
    int *p = &x;
    int *k = p++;
    int r = p - k;
    printf("%d", r);
}
A1
B4
C5
D0
Lời giải
Đáp án đúng: "1". Phép tăng sau p++ nộp cho k giá trị cũ của p rồi mới đẩy p sang ô int kế tiếp, nên k trỏ vào x còn p trỏ vào ô liền sau. Hiệu hai con trỏ cùng kiểu trong C được tính theo số phần tử chứ không theo byte: trình biên dịch lấy khoảng cách byte rồi chia cho kích thước kiểu, vì vậy p trừ k bằng 1. Ý "4" sai vì 4 chính là khoảng cách tính bằng byte khi int chiếm 4 byte, tức là bỏ qua bước chia cho kích thước kiểu; nó lại trùng với giá trị của x nên càng dễ nhầm. Ý "5" sai vì không có phép tính nào cộng thêm 1 vào giá trị của x. Ý "0" sai vì nó cho rằng p++ chưa kịp có tác dụng hoặc k mãi mãi đi theo p; cần công bố rằng đây là khuyết điểm của đề, bộ khoá đi kèm ghi đúng giá trị 0 trong khi ngữ nghĩa của phép tăng sau buộc p và k phải lệch nhau đúng một phần tử.
Mở trang câu hỏi này →
12What will be the output of the following C code?4 lựa chọncó code
Đề bài
#include <stdio.h>
void main()
{
    int k = 5;
    int *p = &k;
    int **m  = &p;
    **m = 6;
    printf("%d\n", k);
}
A5
BRun time error
C6
DJunk
Lời giải
Đáp án đúng: "6". Con trỏ p giữ địa chỉ của k, còn m giữ địa chỉ của p. Khi viết **m, lần lấy nội dung thứ nhất đi từ m sang p, lần thứ hai đi từ p sang chính ô nhớ của k, nên **m = 6 ghi số 6 thẳng vào ô của k. Vì k và **m là hai con đường tới cùng một ô, printf đọc ra 6. Đây là bản chất của con trỏ nhiều cấp: chúng không sao chép giá trị mà chỉ nối thêm một chặng đường tới ô nhớ gốc. Ý "5" sai vì 5 chỉ là giá trị ban đầu, nó đã bị ghi đè trước lúc in. Ý "Run time error" sai vì cả hai con trỏ đều trỏ vào biến còn sống trong hàm, không có địa chỉ nào không hợp lệ. Ý "Junk" sai vì k đã được khởi tạo rồi sau đó còn được gán tường minh, không còn chỗ nào để giá trị rác xen vào.
Mở trang câu hỏi này →
13What will be printed by the code below?4 lựa chọncó code
Đề bài
#include <stdio.h>
#include <stdlib.h>
int main() {
    int *p = (int*) malloc(sizeof(int));
    *p = 50;
    printf("%d", *p);
    free(p);
    return 0;
}
AAddress of p
BGarbage value
C50
DCompilation error
Lời giải
Đáp án đúng: "50". Lời gọi malloc xin một khối nhớ vừa đủ cho một int và trả về địa chỉ khối đó, p giữ địa chỉ này. Lệnh *p = 50 ghi số 50 vào chính khối vừa xin, nên khi printf đọc *p nó lấy ra 50. Thứ tự các lệnh là điều cốt yếu: giá trị được in trước, chỉ sau đó free mới trả khối nhớ về cho hệ thống, nên không có chuyện đọc vào vùng đã giải phóng. Ý "Address of p" sai vì đặc tả %d đi với *p, tức là nội dung tại địa chỉ, chứ không phải bản thân địa chỉ. Ý "Garbage value" sai vì malloc đúng là không xoá vùng nhớ, nhưng ô đó đã được gán tường minh trước khi đọc. Ý "Compilation error" sai vì mã đã nạp stdlib.h cho malloc và ép kiểu con trỏ trả về đúng cách, mọi lệnh đều hợp lệ.
Mở trang câu hỏi này →
14What is a pointer in C programming?4 lựa chọn
AA variable stores anything
BA variable stores address of another variable or a variable stores address of the dynamically allocated memory
CAn address in the memory
DA variable stores any number
Lời giải
Đáp án đúng: "A variable stores address of another variable or a variable stores address of the dynamically allocated memory". Con trỏ trước hết là một biến, nên nó có ô nhớ riêng và có kiểu; thứ nó chứa là địa chỉ, có thể là địa chỉ của một biến khác lấy bằng toán tử lấy địa chỉ, hoặc địa chỉ của khối nhớ xin được từ malloc. Kiểu của con trỏ không để trang trí: nó quyết định bước nhảy khi làm phép tính trên con trỏ và quyết định cách đọc dữ liệu tại địa chỉ ấy. Ý "A variable stores anything" sai vì nói vậy thì mọi biến đều là con trỏ, định nghĩa mất hết ý nghĩa. Ý "An address in the memory" sai vì nó lẫn giữa giá trị và vật chứa: địa chỉ là nội dung mà con trỏ giữ, còn con trỏ là biến giữ nội dung đó. Ý "A variable stores any number" sai vì con trỏ không chứa số tuỳ ý, nó chỉ hợp lệ khi giữ địa chỉ của một ô nhớ có thật hoặc giá trị rỗng.
Mở trang câu hỏi này →
15What will be the output of the C program?4 lựa chọncó code
Đề bài
char temp;
char arr[10] = {1, 2, 3, 4, 5, 6, 7, 8};
temp = (arr + 1)[2];
printf("%d\n", temp);
A1
B2
C3
D4
Lời giải
Đáp án đúng: "4". Cách viết chỉ số trong C chỉ là đường tắt của phép tính trên con trỏ: viết x[i] đồng nghĩa với lấy nội dung tại x cộng i. Vì vậy (arr + 1)[2] chính là lấy nội dung tại arr cộng 1 cộng 2, tức là arr[3]. Mảng được khởi tạo bằng các số từ 1 đến 8 nên arr[3] mang giá trị 4; kiểu phần tử là char nhưng các giá trị khởi tạo là số nguyên nhỏ, và đặc tả %d in ra số 4 chứ không in ký tự. Ý "1" sai vì 1 nằm ở arr[0], giá trị đó chỉ ra nếu bỏ cả hai lượng cộng. Ý "2" sai vì 2 nằm ở arr[1], ứng với việc chỉ cộng 1 mà bỏ mất chỉ số 2. Ý "3" sai vì 3 nằm ở arr[2], đó là kết quả nếu quên lượng cộng 1 và chỉ đọc arr[2].
Mở trang câu hỏi này →
Đề bài
#include <stdio.h>
void level2(int** ppa)
{
    printf("%d\n", **ppa);
}
void level1(int* pa)
{
    level2(&pa);
}
main()
{
    int a = 10;
    level1(&a);
}
AThe address of variable a
BThe address of the pointer pa
CThe address of the double pointer ppa
D10
Lời giải
Đáp án đúng: "10". Biến a mang giá trị 10; lời gọi level1(&a) truyền địa chỉ của a nên tham số pa trỏ tới a. Trong level1, phép lấy địa chỉ của chính tham số pa cho một con trỏ hai cấp, và level2 nhận nó dưới tên ppa. Bỏ một lớp sao thì được lại con trỏ pa, bỏ lớp thứ hai thì lấy nội dung chỗ pa trỏ tới, tức a, nên biểu thức hai lớp sao cho 10 và đặc tả %d in ra số nguyên 10. Kết quả "The address of variable a" ứng với việc chỉ bỏ một lớp sao. Kết quả "The address of the pointer pa" ứng với việc in thẳng ppa mà không bỏ lớp nào. Kết quả "The address of the double pointer ppa" còn cần lấy địa chỉ của ppa, thứ mã này không làm. Thêm nữa, ba kết quả địa chỉ đều lệch kiểu với đặc tả đang dùng: in địa chỉ phải dùng %p, còn %d luôn đọc đối số như một số nguyên.
Mở trang câu hỏi này →
17What is the output?4 lựa chọncó code
Đề bài
#include <stdio.h>
int main(){
    int a=6,b=15;
    int* ptr1= &a, *ptr2=&b;
    *ptr1 +=12-b+ (*ptr2);
    *ptr2 = b + a- 2*(*ptr1);
    printf("%d, %d, %d", a,b,b+a*3);
}
A18, -3, 51
B12, 3, 39
CSyntax error
DRuntime error
Lời giải
Đáp án đúng: "18, -3, 51". Hai con trỏ ptr1 và ptr2 lần lượt trỏ tới a và b, nên ghi qua con trỏ là ghi thẳng vào hai biến đó. Lệnh thứ nhất tính 12 - b + (*ptr2) với b bằng 15, được 12 - 15 + 15 là 12, rồi cộng dồn vào a nên a thành 6 + 12 là 18. Lệnh thứ hai tính b + a - 2*(*ptr1) với b bằng 15 và a đã là 18, được 15 + 18 - 36 là -3, gán qua ptr2 nên b thành -3. Lệnh in xuất a là 18, b là -3, còn b + a*3 do phép nhân ưu tiên hơn phép cộng nên bằng -3 + 54 là 51. Dãy "12, 3, 39" ứng với việc lấy 12 làm giá trị mới của a thay vì cộng dồn vào giá trị cũ. Kết luận "Syntax error" không đúng, mọi lệnh đều hợp cú pháp kể cả việc khai hai con trỏ trên một dòng. Kết luận "Runtime error" cũng không, hai con trỏ đều trỏ vào biến cục bộ còn sống nên không có truy cập bất hợp lệ.
Mở trang câu hỏi này →
18What will the following program print?4 lựa chọncó code
Đề bài
#include <stdio.h>

int hours_and_minutes2(int total, int *pminutes) {
    return (*pminutes = total % 60, total / 60);
}

int main() {
    int minutes;
    printf("Hours: %d, Minutes: %d\n", hours_and_minutes2(135, &minutes), minutes);
    return 0;
}
AHours: 2, Minutes: 15
BHours: 2, Minutes: 30
CHours: 3, Minutes: 15
DHours: 3, Minutes: 30
Lời giải
Đáp án đúng: "Hours: 2, Minutes: 15". Lệnh trả về của hàm dùng toán tử phẩy: vế trái gán 135 phần trăm 60, tức phần dư 15, vào chỗ pminutes trỏ tới chính là biến minutes của hàm chính; vế phải lấy 135 chia 60 mà cả hai đều là số nguyên nên đó là phép chia lấy phần nguyên, cho 2. Giá trị của một biểu thức phẩy chính là giá trị vế phải, nên hàm trả về 2 và lệnh in xuất 2 cho giờ, 15 cho phút. Dãy "Hours: 2, Minutes: 30" đòi phần dư 30, nhưng 135 bớt đi hai lần 60 chỉ còn 15. Dãy "Hours: 3, Minutes: 15" đòi thương 3, trong khi ba lần 60 đã vượt quá 135. Dãy "Hours: 3, Minutes: 30" sai cả hai phần theo đúng hai lý do vừa nêu. Cần biết thêm rằng chuẩn C không ấn định thứ tự tính các đối số của một lời gọi, nên mã kiểu này chỉ cho kết quả như trên khi lời gọi hàm được tính trước lúc lấy giá trị của minutes.
Mở trang câu hỏi này →
19Assume we have the following code:4 lựa chọncó code
Đề bài
int i=4;
int *p = &i;

What is the result of the following expression: ++*p?

A5
B4
C9
D12
Lời giải
Đáp án đúng: "5". Con trỏ p giữ địa chỉ của i, nên biểu thức lấy nội dung chỗ p trỏ tới chính là biến i và dùng được ở cả hai vai, đọc lẫn ghi. Hai toán tử một toán hạng ở đây cùng mức ưu tiên và kết hợp từ phải sang trái, nên phép tăng được áp lên giá trị đã lấy ra: i tăng từ 4 lên 5 trước khi biểu thức cho giá trị, và giá trị đó cũng là 5. Giá trị "4" là giá trị cũ của i, nó chỉ xuất hiện khi dùng dạng tăng sau viết với ngoặc quanh phần lấy nội dung, khi ấy biểu thức cho 4 còn i vẫn thành 5. Giá trị "9" cần cộng thêm năm đơn vị, không có phép nào trong mã làm việc đó. Giá trị "12" cần một phép nhân hoặc một lượng cộng lớn hơn hẳn, cũng không có nguồn nào sinh ra. Điều dễ lẫn là dạng tăng đặt sau tên con trỏ, vì khi đó phép tăng tác động lên con trỏ chứ không lên giá trị được trỏ tới.
Mở trang câu hỏi này →
20What will be the output of the following program?4 lựa chọncó code
Đề bài
void func(int *p){
    int j =11;
    *p = j;
}
int main() {
    int i = 1;
    int *p = &i;
    func(p);
    printf("%d,%d", i, *p);
    getchar();
    return 0;
}
A11,11
B1,1
C0,0
D0,1
Lời giải
Đáp án đúng: "11,11". Biến i của hàm chính bằng 1 và p giữ địa chỉ của i, nên truyền p vào func là truyền chính địa chỉ đó chứ không phải một bản sao của giá trị. Trong func, biến cục bộ j bằng 11 và lệnh ghi qua con trỏ đặt 11 vào ô nhớ mà p trỏ tới, tức ghi thẳng vào i; j chết khi hàm kết thúc nhưng giá trị đã nằm lại trong i. Sau lời gọi, i là 11 và nội dung chỗ p trỏ tới cũng là 11 vì p vẫn trỏ vào i, nên lệnh in xuất hai số 11 cách nhau bởi dấu phẩy. Dãy "1,1" là kết quả nếu hàm chỉ gán cho bản sao tham số, chẳng hạn cho con trỏ trỏ sang j, khi đó i không đổi. Dãy "0,0" cần một phép đặt về không, không có trong mã. Dãy "0,1" còn đòi hai số khác nhau, trong khi i và nội dung chỗ p trỏ tới luôn là cùng một ô nhớ nên không thể lệch nhau.
Mở trang câu hỏi này →