1. What are pointer?
Pointer
Printing a Memory Address in Pascal
In Pascal, we can assign the address of a variable to a pointer variable using the address operator (@). We use this pointer to manipulate and access the data item. However, if for some reason, we need to work with the memory address itself, we need to store it in a word type variable.
NIL Pointer
It is always a good practice to assign a NIL value to a pointer variable in case you do not have exact address to be assigned. This is done at the time of variable declaration. A pointer that is assigned NIL points to nowhere.
Pascal Pointers in Detail
Pointers have many but easy concepts and they are very important to Pascal programming. There are following few important pointer concepts, which should be clear to a Pascal programmer
Pascal – Pointer arithmetic
Pascal – Array of pointers
Pascal – Pointer to pointer
Passing pointers to subprograms in Pascal
Return pointer from subprograms in Pascal
Ref
http://www.tutorialspoint.com/pascal/pascal_pointer_arithmetic.htm
2. Virtual Memory – Bộ nhớ ảo:
3. Virtual Address – Địa chỉ ảo:
– Trong cái vùng bộ nhớ ảo ở trên đã nói, để cho tiến trình (process) sử dụng, hệ điều hành dễ hiểu, hai bên này cùng nhau quy định chia nhỏ ra theo từng byte, và đánh số từ 1 đến hết
– Ô nhớ đã được đánh số là i thì ta nói địa chỉ của cái ô nhớ đó là i
Example: int a;
=> Trong tiến trình hiểu là: a nằm trong cái ô thứ 0x006e6e1 thì a có địa chỉ là 0x006e6e1
=> Trong hệ điều hành hiểu là: cái địa chỉ này tương đương với ô nào đó trong thanh RAM mà ta quản lý
4. Con trỏ là gì?
– Miền giá trị của biến con trỏ là địa chỉ ô nhớ
– Là môt biến bình thường
– Chứa cái ‘địa chỉ ảo’.
5. Pointer declaration and initialization pointer in C and Pascal
Pointer declaration (C/C++)
Type *pointer;
void *p;
char *p;
double *p;
(we said p is pointer, not said *p is pointer)
Pointer declaration (Pascal)
var variables:^pointer;
var i:^integer;
var p:pointer;
var p:^char;
var p:^double;
(we said p is pointer, not said ^p is pointer)
Initialization pointer pointer (C/C++)
pointer = address
int a = 7777;
int *p = &a;
int *p;
P = &a;
Initialization pointer pointer (Pascal)
variables:@address
var x:integer
var p:pointer
p := @x;
Notes:
a = 3 & 2; // toán tử & hai ngôi
p = &a; // toán tử & một ngôi
scanf (“%d”, &a); // toán tử & một ngôi, là toán tử lấy địa chỉ một biến
when you declare; int *p = &a (or p = &a) <===> *p Equal with a
a = 2; <=> *p = 2;
a++; <=> (*p)++; // (*p) trong ngoặc vì toán tử * có độ ưu tiên thấp hơn ++
b = c + a – 200; <=> b = c + (*p) – 200;
(*p) = (*p) – 777; <=> a = a – 777;
scanf(“%d”, &a); <=> scanf(“%d”, p);
6. Pointer arithmetic – các phép toán trên con trỏ
Assignments – Phép gán:
– Tất cả các loại con trò đều có phép gán
– Phép gán với con trỏ yêu cầu vế trái là 1 con trỏ và vế phải là 1 địa chỉ
– Phép gán yêu cầu sự tương xứng về kiểu dữ liệu, nếu ko tương xứng chúng ta phải ép kiểu
Example: p=(int*)7777;
– p có kiểu dữ liệu là int*
– còn 7777 là 1 hằng số nguyên, nên phải ép kiểu về int* rồi thực hiện phép gán
Compare – Phép so sánh:
– Phép so sánh bằng dùng để:
o Kiểm tra hai con trỏ có trỏ vào cùng một vùng nhớ hay không?
o Kiểm tra một con trỏ có đang trỏ vào NULL hay không? (trong trường hợp cấp phát động, mở file, resource, …)
– Phép so sánh lớn, nhỏ hơn <, >, <=, >= dùng để:
o Kiểm tra độ thấp cao giữa hai địa chỉ, con trỏ nào nhỏ hơn thì trỏ vào địa chỉ thấp hơn
o Được so sánh mọi con trỏ với 0, vì 0 chính là NULL
1st Example:
// huuvi168@gmail.com
// Last modified: 2016-06-28
int a=778,*p=&a;
double *y;
p==&a;
main==0;
p==0;
y==0;
2nd Example:
int a=197,*p=&a;
double b=0,*x=&b;
// so sánh 2 con trỏ
int)p==(int)x;
p==(int *)x;
(double*)p==x;
(void*)p==(void*)x;
p==(void*)x;
(float*)p==(float*)x;
//so sánh con trỏ với số nguyên
p==(int*)9999;
int(p)==9999;
// con trỏ void có thể so sánh với con tất cả con trỏ khác
(int(*)())p==main;
Incrementing a Pointer, Decrementing a Pointer – Phép cộng trừ, tăng giảm: + += – -= — ++ +
– Tăng/ giảm con trỏ p đi 1 đơn vị là cho p trỏ đến ô nhớ bên cạnh phía dưới/trên.
Chú ý:
+ Khi tăng giảm con trỏ p đo 1 đơn vị không có nghĩa là trỏ sang byte bên cạnh
+ Việc tăng giảm con trỏ đi 1 đơn vị phụ thuộc vào kiểu dữ liệu và nó trỏ đến, quy tắc là
p+1 => giá trị chứa trong p + sizeof (kiểu dữ liệu của biến mà p trỏ đến)
Tuy nhiên:
+ Không có phép tăng giảm trên con trỏ void
+ Không có phép tăng giảm trên con trỏ hàm
+ Không có phép cộng 2 con trỏ với nhau
+ Phép trừ 2 con trỏ trả về độ lệch pha giữa 2 con trỏ
Example:
void main()
{
char xau[200];
printf("Nhap xau : ");
scanf("%[a-zA-Z ]",xau);
//Viết hoa xâu (duyệt xuôi)
printf("Viet hoa : ");
//viết đầy đủ sẽ là (char *p=xau;*p!=NULL;p++)
for (char *p=xau;*p;p++) //p trỏ đến xâu; kí tự trỏ đến khác NULL;p=p+1
printf("%c",toupper(*p));
//Viết đảo ngược xâu (duyệt ngược)
printf("nDao nguoc xau : ");
// cho p trỏ vào từ cuối cùng; p còn lớn hơn xau;p=p-1
for(char *p=xau+strlen(xau)-1;p>=xau;p--)
printf("%c",*p);
getch();
}
7. Pointer Constant – Hằng con trỏ? Con trỏ hằng
Hằng Con Trỏ | Con Trỏ Hằng |
---|---|
Những con trỏ mà chỉ trỏ cố định vào 1 vùng nhớ , những con trỏ này ko có khả năng trỏ vào vùng nhớ khác, ko thay đổi được (1) -> gọi là Hằng con trỏ | Những con trỏ mà trỏ vào một vùng nhớ cố định, con trỏ này chỉ có tác dụng trỏ đến, chứ không có khả năng thay đổi giá trị của vùng nhớ này, con trỏ này được ứng dụng gần như là tác dụng của phương thức hằng trong OOP (2) -> gọi là Con trỏ hằng |
Example: Hằng con trỏ
void main()
{
char buf[] = "bonjour";
char * const p = buf;
p++; // báo lỗi tại đây
p[4]++; // hoàn toàn có thể thay đổi giá trị vùng nhớ mà p trỏ đến
}
Example: Con trỏ Hằng:
void main()
{
char *p="learn tech tips";
p++;
(*p)++; // không báo lỗi biên dịch nhưng lỗi run-time
p[2]='b'; // không báo lỗi biên dịch nhưng lỗi run-time)
}
char buf[] = "bonjour";
char const *p = buf; // const char *p = buf;
p++; /* đúng */
p[4]++; /* ko được, sai */
Mục đích và ứng dụng Con trỏ Hằng
Ứng dụng lớn nhất của char const * đó là chú ý khi khai báo và sử dụng các hàm trả về const
const char *FunctionofAnotherPeople(void)
{
return "abc";
}
void HamCuaToi(void)
{
//gọi và sử dụng đến kết quả hàm bên trên thế nào?
char const *pstr=FunctionofAnotherPeople(); // how to used?
}
Vậy ta sẽ cài đặt hàm của mình như sau
// đối với trường hợp hằng con trỏ là tham số hình thức thì
// void ham(const int *) và void ham(int const *) => là như nhau, từ const khi đóng góp vào trong tham số hình thức là như nhau.
void input(const int *a,int n)
{
//xử lý gì đó
}
void main()
{
int a[100]={1, 77},
int n=2;
input(a,n); // khi sử dụng hàm này có nghĩa là hàm này không thay đổi mảng a của mình đâu, yên tâm sử dụng, nếu có lỗi gì đó thì ko phải sinh ra từ đây...
}
Phụ lục, Con trỏ Hằng (nâng cao)
int a=3;
const int *p;
p=&a; // Bản thân p thì có thể thay đổi, cho p gán vào chỗ khác được tuy nhiên
(*p)++; // Báo lỗi
8. Array – Pointer
Khi ta khai báo mảng thì tương đương với:
Xin cấp phát 1 vùng nhớ có kich thước như khai báo và khai báo ra một Hằng con trỏ trỏ vào đầu vùng nhớ đó?
Bài toán ở trên:
int a[100];
– Có thể coi a là một hằng con trỏ trỏ vào phần tử thứ 0 của mảng, a mang đầy đủ tính chất của một hằng con trỏ nhưng có thêm 1 số khác biệt nhỏ (ví dụ khi dùng size of)
– Các phép toán nhằm làm a trỏ tới vùng khác (thay đổi giá trị của a) là ko thể (++ — = )
– a tương đương với &a[0]
– a+i tương đương với &a[i]
– *a tương đương với a[0]
– *(a+i) tương đương với a[i]
– 3[a] tương đương với *(a+3) tương đương với a[3]
// huuvi168@gmail.com
void main()
{
float a[100];
int n;
//nhập n
printf("Input n :");
scanf("%d",&n);
// nhập mảng
for(int i=0;i<n;i++)
{
printf("Input the elem: %d",i+1);
scanf("%f",a+i);
}
// xuất mảng
printf("Array output : n");
for(int i=0;i<n;i++)
printf("%f ",*(a+i));
getch();
}
#include <stdio.h>
#include <conio.h>
void main()
{
int a[100]={0,1,2,3,4,5,6};
printf("%d",2[a]); //in ra 2, tại sao vậy ?
getch();
}
2[a] là gì?
Thật ra :
2[a] trình biên dịch sẽ hiểu là *(2+a)
*(2+a) hoàn toàn tương đương với *(a+2)
mà *(a+2) chính là a[2]
vậy 2[a] cũng đơn giản là a[2]
9. String – Xâu Ký tự
– Xâu kí tự là trường hợp đặc biệt của mảng 1 chiều khi mà cách thành phần của mảng là 1byte
– Xâu kí tự kết thúc bằng NULL. NULL là 1 kí tự đặc biệt có mã là 0,
Có 3 cách viết NULL trong C như sau : NULL , ‘