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. Trang 2/3 — câu 21–40.

Danh sách câu hỏi

40/41 câuCòn 1
Đề 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 →
22What 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 →
23What 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 →
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 →
25Assume 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 →
26What will be the output of the following program?4 lựa chọncó code
Đề bài
int main()
{
        int i = 100;
        int *p = &i;
        *p +=2;
        printf("%d, %d", i, *p);
        getchar();
        return 0;
}
A102, 102
B100, 102
C100, 100
D102, 100
Lời giải
Đáp án đúng: "102, 102". Con trỏ p được gán địa chỉ của i nên nó trỏ thẳng vào ô nhớ của i; phép cộng dồn qua dấu sao không tạo bản sao nào mà cộng 2 ngay tại ô đó, vì vậy i trở thành 102. Khi printf chạy, cả i và nội dung được p trỏ tới đều đọc cùng một ô nhớ nên hai số in ra giống nhau; đó là bản chất của bí danh qua con trỏ, hai cách gọi tên cho cùng một vùng dữ liệu. Lựa chọn "100, 102" đòi i giữ nguyên trong khi vùng được trỏ tới đổi, chuyện chỉ xảy ra nếu p trỏ vào một biến khác. Lựa chọn "100, 100" là kết quả nếu phép cộng áp lên bản thân con trỏ, khi đó i không đổi nhưng con trỏ lại đọc sang vùng nhớ lạ. Lựa chọn "102, 100" vừa đòi i đổi vừa đòi phép lấy nội dung cho ra giá trị cũ, mâu thuẫn vì chúng là cùng một ô nhớ.
Mở trang câu hỏi này →
Aint* a = (int*)malloc(5*sizeof(int));
Bint a[5];
Cint a[5][5];
Dfree(a);
Lời giải
Đáp án đúng: "int* a = (int*)malloc(5*sizeof(int));". Cấp phát động nghĩa là xin bộ nhớ lúc chương trình đang chạy, với kích thước có thể tính ra tại thời điểm đó, và vùng xin được nằm trên heap, sống tới khi được giải phóng. Hàm malloc làm đúng việc đó: nhận số byte cần, trả về địa chỉ đầu vùng nhớ hoặc con trỏ rỗng khi thất bại, nên phải gán vào một con trỏ. Lựa chọn "int a[5];" là mảng tự động, kích thước cố định ghi sẵn lúc dịch và vùng nhớ bị thu hồi khi ra khỏi khối. Lựa chọn "int a[5][5];" chỉ là mảng hai chiều, bản chất vẫn là cấp phát theo khai báo. Lựa chọn "free(a);" đứng ở đầu bên kia của vòng đời: nó trả vùng nhớ đã cấp phát về cho hệ thống, không xin thêm ô nhớ nào.
Mở trang câu hỏi này →
28What does the following code do?4 lựa chọncó code
Đề bài
int a = 5, b = 7;
int *pa = &a, *pb = &b;
*pa = *pa + *pb;
AAdds values at addresses a and b
BSwaps the values
CStores the address of b in a
DMultiplies both numbers
Lời giải
Đáp án đúng: "Adds values at addresses a and b". Con trỏ thứ nhất trỏ vào a, con trỏ thứ hai trỏ vào b, nên hai phép lấy nội dung chính là hai ô nhớ đó. Dòng lệnh đọc nội dung của cả hai ô, cộng lại rồi ghi tổng trở lại vào ô mà con trỏ thứ nhất trỏ tới, vì vậy a thành 12 còn b vẫn là 7. Toàn bộ việc diễn ra trên dữ liệu được trỏ tới, không có con trỏ nào bị gán lại. Lựa chọn "Swaps the values" sai vì đổi chỗ cần một biến tạm cùng hai phép gán, còn ở đây b không hề bị ghi. Lựa chọn "Stores the address of b in a" sai vì muốn vậy phải gán con trỏ này bằng con trỏ kia hay gán cho a địa chỉ của b, trong khi dòng lệnh chỉ làm việc với nội dung sau dấu sao. Lựa chọn "Multiplies both numbers" sai vì toán tử trong biểu thức là dấu cộng, không phải dấu nhân.
Mở trang câu hỏi này →
29What is the output?4 lựa chọncó code
Đề bài
int arr[] = {1, 2, 3, 4};
printf("%d", *(arr + 2));
A1
B2
C3
D4
Lời giải
Đáp án đúng: "3". Tên mảng dùng trong biểu thức suy biến thành địa chỉ phần tử đầu, và số học con trỏ đếm theo phần tử chứ không theo byte, nên cộng 2 vào tên mảng cho ra địa chỉ của phần tử có chỉ số 2. Dấu sao lấy nội dung tại địa chỉ đó nên in ra 3. Đây đúng là nghĩa gốc của phép viết chỉ số: ngôn ngữ định nghĩa truy cập mảng chính là phép lấy nội dung của địa chỉ đầu cộng độ lệch. Lựa chọn "1" là phần tử ở chỉ số 0, tức kết quả nếu không cộng độ lệch nào. Lựa chọn "2" là phần tử ở chỉ số 1, ứng với cách đếm bắt đầu từ 1 thay vì từ 0. Lựa chọn "4" là phần tử ở chỉ số 3, sẽ đúng nếu độ lệch viết là 3.
Mở trang câu hỏi này →
Đề bài
#include <stdio.h>
void swap(int *px, int *py)
{
    int z;
    z=*px;
    *px=*py ;
    *py=z ;
}
int main()
{
    int a=15, b=21 ;
    swap(&a,&b);
    printf ("%d  %d",a,b);
   return 0;
}
A15 21
B21 15
CError while executing the program
DNone of these
Lời giải
Đáp án đúng: "21 15". Hàm main truyền địa chỉ của a và địa chỉ của b, nên hai tham số con trỏ trỏ thẳng vào hai biến của main. Thân hàm giữ nội dung ô thứ nhất vào biến tạm, ghi nội dung ô thứ hai sang ô thứ nhất, rồi ghi biến tạm sang ô thứ hai; mọi phép ghi đều đi qua dấu sao nên tác động lên chính a và b chứ không lên bản sao. Sau lời gọi, a mang 21 và b mang 15. Lựa chọn "15 21" là trạng thái ban đầu, chỉ đúng nếu hàm nhận hai int theo giá trị và đổi chỗ trên bản sao. Lựa chọn "Error while executing the program" sai vì địa chỉ của hai biến đang sống trong main là hợp lệ, việc ghi vào đó không gây sự cố nào. Lựa chọn "None of these" không dùng được vì đã có một lựa chọn khớp đúng kết quả thật của chương trình.
Mở trang câu hỏi này →
Apointers
Bvalue
Ctype
Daddress
Lời giải
Đáp án đúng: "address". Vị trí ô nhớ của một biến được gọi là địa chỉ của biến đó, và toán tử lấy địa chỉ cho ra đúng giá trị này; chính nhờ địa chỉ mà chương trình đọc ghi được dữ liệu, mà hàm sửa được biến của nơi gọi, và mà số học con trỏ đi lại được trên mảng. Lựa chọn "pointers" nói về biến dùng để chứa địa chỉ, tức cái hộp, chứ không phải bản thân vị trí ô nhớ. Lựa chọn "value" là dữ liệu đang nằm trong ô nhớ, thứ thay đổi được trong khi địa chỉ của biến thì cố định suốt thời gian biến tồn tại. Lựa chọn "type" là kiểu dữ liệu, nó quyết định ô nhớ rộng bao nhiêu byte và nội dung được hiểu theo nghĩa nào, nhưng không nói gì về vị trí.
Mở trang câu hỏi này →
32What is the output of the following code snippet?4 lựa chọncó code
Đề bài
void main()
{
        int const *p = 5;
        printf("%d", ++(*p));
        getchar();
}
ACompile error
B5
CNULL
D6
Lời giải
Đáp án đúng: "Compile error". Khai báo ở đây nói p là con trỏ tới int có tính bất biến, nghĩa là không được phép ghi vào vùng mà p trỏ tới. Vì vậy phép tăng áp lên nội dung được trỏ tới là ghi vào một đối tượng bất biến và trình dịch phải báo lỗi, không cần biết p đang trỏ đi đâu. Mã còn một chỗ sai nữa ngay trên đó: gán số 5 cho một con trỏ mà không ép kiểu cũng là vi phạm ràng buộc kiểu. Lựa chọn "5" giả định lệnh in chạy được và phép tăng không có hiệu lực, nhưng chương trình không bao giờ tới được bước thực thi. Lựa chọn "6" giả định phép tăng thành công, điều mà tính bất biến chặn lại ngay lúc dịch; hơn nữa nếu có chạy thì việc đọc nội dung tại địa chỉ 5 cũng làm chương trình gãy. Lựa chọn "NULL" không ứng với gì vì p được gán 5 chứ không phải hằng con trỏ rỗng.
Mở trang câu hỏi này →
33What does the following program print?4 lựa chọncó code
Đề bài
#include <stdio.h>

int main()
{
    int a = 4;
    int *b = &a;

    a -= 1;
    *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". Câu int *b = &a cho b giữ địa chỉ của a, nên từ đó a và *b là hai cách gọi cùng một ô nhớ chứ không phải hai bản sao. Lệnh a -= 1 hạ ô đó từ 4 xuống 3, rồi *b -= 1 hạ tiếp chính ô đó xuống 2; vậy cả hai cách đọc đều cho 2 và printf in hai số giống nhau. Dãy "2 1" giả định *b có ô riêng cũng bắt đầu từ 4 rồi chỉ bị trừ một lần, tức hiểu con trỏ thành bản sao. Dãy "3 1" giả định a chỉ chịu phép trừ thứ nhất còn phép trừ thứ hai tác động lên một vùng khác. Dãy "3 3" chỉ đúng nếu phép trừ qua con trỏ không có tác dụng gì, trong khi *b -= 1 ghi thẳng vào ô mà b trỏ tới.
Mở trang câu hỏi này →
A1 bytes
B2 bytes
C4 bytes
D8 bytes
Lời giải
Đáp án đúng: "4 bytes". Kiểu của con trỏ quyết định trình dịch đọc ghi bao nhiêu byte khi lấy giá trị qua dấu sao, và bước nhảy khi cộng trừ con trỏ. Trên các trình dịch phổ thông ngày nay, kiểu int chiếm bốn byte, nên *p làm việc trên bốn byte và p + 1 nhảy bốn byte. Số "1 bytes" là kích thước của char, kiểu duy nhất mà chuẩn ấn định bằng một byte. Số "2 bytes" là kích thước thường thấy của short, và cũng là kích thước int trên những trình dịch mười sáu bit rất cũ. Số "8 bytes" là kích thước của double hay long long, và cũng là chỗ chứa chính biến con trỏ trên nền sáu mươi tư bit, nhưng câu hỏi hỏi vùng nhớ được truy cập qua con trỏ chứ không hỏi chỗ chứa con trỏ.
Mở trang câu hỏi này →
Đề bài
void input(int* a, int n);
AIt is a pointer to the first element of the array
BIt holds the array size
CIt defines the function return type
DIt stores the index of the element
Lời giải
Đáp án đúng: "It is a pointer to the first element of the array". Trong C mảng không truyền được theo giá trị: viết tên mảng ở lời gọi thì nó tự suy biến thành địa chỉ phần tử đầu, nên tham số int* a nhận đúng địa chỉ đó, và trong hàm a[i] tương đương *(a + i), cho phép hàm ghi thẳng vào mảng của nơi gọi. Vì địa chỉ không mang theo số phần tử, hàm cần thêm tham số n, và đó mới là chỗ giữ kích thước, nên "It holds the array size" gán sai vai. Mô tả "It defines the function return type" sai vì kiểu trả về là void, viết trước tên hàm, chẳng liên quan tới danh sách tham số. Mô tả "It stores the index of the element" cũng sai vì chỉ số là một số nguyên thường, dùng bên trong hàm khi duyệt mảng, không phải một con trỏ.
Mở trang câu hỏi này →
Aprintf("a[3] = %d\n", a[3]);
Bprintf("*(a + 3) = %d\n", *(a + 3));
Cprintf("&a[3] = %p\n", (void*)&a[3]);
DAll the above
Lời giải

Đáp án đúng: "All the above". Phần tử thứ tư nằm ở chỉ số 3 vì chỉ số đếm từ 0, và chuẩn C định nghĩa a[3] chính là *(a + 3), nên hai lối viết khác nhau trên mặt chữ lại sinh ra cùng một phép truy cập; lấy &a[3] thì chạm tới đúng phần tử đó ở mức địa chỉ. Cả ba lệnh in đều hợp lệ và đều nói về phần tử thứ tư, nên chỉ lựa chọn gộp mới trả lời đủ. Lệnh "printf("a[3] = %d\n", a[3]);" đúng nhưng chỉ là một trong ba cách. Lệnh "printf("*(a + 3) = %d\n", *(a + 3));" cũng đúng và theo định nghĩa là cùng một thao tác với lối dùng chỉ số, nên không thể đúng một mình. Lệnh "printf("&a[3] = %p\n", (void*)&a[3]); " in địa chỉ của phần tử thứ tư, vẫn là truy cập hợp lệ tới nó, chỉ khác là lấy địa chỉ thay vì lấy giá trị.

Mở trang câu hỏi này →
AAddress of the variable a
BValue of the variable a or 5
CSize of the variable a or 8
DType of the variable a or double
Lời giải
Đáp án đúng: "Address of the variable a". Dấu và đứng trước một toán hạng là phép lấy địa chỉ: nó cho biết vị trí trong bộ nhớ nơi biến được cấp chỗ, và kiểu của kết quả là con trỏ tới kiểu của biến, ở đây là con trỏ double. Giá trị này thường in bằng %p sau khi ép sang con trỏ void, và chính nó là thứ phải truyền cho scanf hay cho hàm muốn ghi vào biến. Mô tả "Value of the variable a or 5" là thứ lấy được khi đọc chính a, không cần toán tử nào; dù a khởi tạo từ số nguyên 5 thì nó vẫn là double mang giá trị 5.0. Mô tả "Size of the variable a or 8" là việc của sizeof. Mô tả "Type of the variable a or double" không phải giá trị mà biểu thức C trả về được; kiểu chỉ tồn tại lúc dịch, chương trình đang chạy không có phép toán nào cho ra tên kiểu.
Mở trang câu hỏi này →
Đề bài
#include<stdio.h>
void updatePosition(int *time, float* position, float v)
{
    if ((*position < 5) && (*position > -5))
        *position += v;
    else
        *position += -0.1*(*position);
    time += 1;
}

main()
{
    float p = 4.0, v = 1;
    int t = 0;
    printf("t = %d, p = %f\n", t, p);
    updatePosition(&t, &p, v);
    updatePosition(&t, &p, v);
    printf("t = %d, p = %f\n", t, p);
}

What is the result displayed to the screen?

At = 0, p = 4.000000 t = 2, p = 6.000000
Bt = 0, p = 4.000000 t = 2, p = 5.000000
Ct = 0, p = 4.000000 t = 2, p = 4.500000
Dt = 0, p = 4.000000 t = 2, p = 4.000000
Lời giải
Đáp án đúng: "t = 0, p = 4.000000 t = 2, p = 4.500000". Lần gọi đầu, giá trị trỏ tới nằm giữa -5 và 5 nên p tăng thêm v, thành 5.0. Lần gọi sau, điều kiện nhỏ hơn 5 đã sai vì p đúng bằng 5.0, nên nhánh else chạy: p cộng thêm -0.1 nhân 5.0, tức giảm 0.5 còn 4.5. Phải nói thẳng một khuyết điểm của đề: lệnh time += 1 chỉ dịch bản sao con trỏ trong hàm chứ không ghi qua dấu sao, nên t thật sự vẫn là 0, mà cả bốn lựa chọn đều in t = 2; vì vậy chỉ giá trị của p phân định được, và 4.500000 là con số duy nhất đúng. Dòng "t = 0, p = 4.000000 t = 2, p = 6.000000" coi như cả hai lần gọi đều vào nhánh cộng v. Dòng "t = 0, p = 4.000000 t = 2, p = 5.000000" dừng ở kết quả lần gọi đầu. Dòng "t = 0, p = 4.000000 t = 2, p = 4.000000" coi như lần gọi sau trả p về giá trị cũ.
Mở trang câu hỏi này →
Đề bài
void swap(int *a, int *b) {
    int t = *a;
    *a = *b;
    *b = t;
}

int main() {
    int x = 5, y = 10;
    swap(&x, &y);
    printf("%d %d", x, y);
    return 0;
}
A10 5
B5 10
C0 0
DCompilation error
Lời giải
Đáp án đúng: "10 5". C truyền tham số theo giá trị, nên muốn hàm sửa được biến của nơi gọi thì phải truyền địa chỉ: lời gọi swap(&x, &y) đưa địa chỉ của x và của y vào hai con trỏ. Trong hàm, t giữ bản sao giá trị đầu là 5, rồi ô mà con trỏ thứ nhất trỏ tới nhận 10 nên x thành 10, cuối cùng ô của con trỏ thứ hai nhận t nên y thành 5. Mọi phép ghi đều qua dấu sao, tức ghi thẳng vào ô nhớ gốc, nên sau lời gọi printf in 10 rồi 5. Dãy "5 10" là thứ tự ban đầu, nó xảy ra nếu hàm nhận hai bản sao int thường và chỉ đổi chỗ bản sao. Dãy "0 0" sai vì không có chỗ nào gán 0. Kết luận "Compilation error" sai vì nguyên mẫu nhận con trỏ int, lời gọi truyền đúng địa chỉ, và phép gán qua dấu sao hoàn toàn hợp lệ.
Mở trang câu hỏi này →
Aint *p;
Bint p*;
Cint +p;
Dint $p;
Lời giải
Đáp án đúng: "int *p;". Khai báo trong C đọc theo lối dùng là gì: dấu sao đứng trước tên nói rằng *p là một int, suy ra p là con trỏ tới int. Vì thế dấu sao thuộc về bộ phận khai báo của tên, viết int *p; hay int* p; đều cùng nghĩa, miễn nó đứng trước tên biến. Dòng "int p*;" đặt dấu sao sau tên, cú pháp không có dạng này nên trình dịch báo lỗi ngay; hậu tố trong khai báo chỉ dành cho ngoặc vuông của mảng và ngoặc tròn của hàm. Dòng "int +p;" dùng dấu cộng, thứ chỉ là toán tử trong biểu thức chứ không phải bộ phận khai báo, nên không tạo được con trỏ. Dòng "int $p;" dùng ký tự không thuộc tập cho phép của tên định danh; tên chỉ gồm chữ cái, chữ số và dấu gạch dưới, nên dòng này sai ngay ở bước tách từ.
Mở trang câu hỏi này →