Background
Break News
How to add local font to Tailwind Css and NextJS? - Tutorial Design Pattern? - Blockchain Technology, How to create own Bitcoin virtual currency - Zustand mordern management state - Design Pattern - Flyweight Pattern? - Docker Full training Topic

[Knowdedge] "Pointer in C++" and "Pascal" From basic to advanced

Wednesday, 29 June 2016
|
Read: Completed in minutes

[Knowdedge] "Pointer in C++" and "Pascal" From basic to advanced

1. What are pointer?

Pointer

A pointer is a dynamic variable, whose value is the address of another variable, i.e., direct address of the memory location. Like any variable or constant, you must declare a pointer before you can use it to store any variable address.

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
https://www.tutorialspoint.com/pascal/pascal_pointer_arithmetic.htm



Để hiểu rõ về con trỏ thì mới các bạn làm quen với các khái niệm: Bộ nhớ ảo, địa chỉ ảo trước nhé bạn!

2. Virtual Memory - Bộ nhớ ảo:

        Quản lý bộ nhớ vật lý (cấp phát, thu hồi) là một vấn đề cực kì phức tạp trong hệ thống máy tính, để bảo đảm sự hiệu quả, đúng đắn, an toàn cho việc quản lý đó, hệ điều hành xây dựng lên các vùng nhớ ảo.

        Trong hệ thống máy tính, bộ nhớ ảo (virtual memory) là một kĩ thuật cho phép một chương trình ứng dụng tưởng rằng mình đang có một dải bộ nhớ liên tục (một không gian địa chỉ), - các hộp tủ liên tục
        Trong khi thực ra phần bộ nhớ này có thể bị phân mảnh trong bộ nhớ vật lý và thậm chí có thể được lưu trữ cả trong đĩa cứng.
        So với các hệ thống không dùng kĩ thuật bộ nhớ ảo, các hệ thống dùng kĩ thuật này cho phép việc lập trình các ứng dụng lớn được dễ dàng hơn và sử dụng bộ nhớ vật lý thực (ví dụ RAM) hiệu quả hơn.

Lưu ý rằng:
-    khái niệm "bộ nhớ ảo" không chỉ có nghĩa "sử dụng không gian đĩa để mở rộng kích thước bộ nhớ vật lý" - nghĩa là chỉ mở rộng hệ thống bộ nhớ để bao gồm cả đĩa cứng.
-    Việc mở rộng bộ nhớ tới các ổ đĩa chỉ là một hệ quả thông thường của việc sử dụng các kĩ thuật bộ nhớ ảo.
-    Định nghĩa của "bộ nhớ ảo" có nền tảng là việc định nghĩa lại không gian địa chỉ bằng một dải liên tục các địa chỉ bộ nhớ ảo để "đánh lừa" các chương trình rằng chúng đang dùng các khối lớn các địa chỉ liên tục.

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ý

=   =>  Trong window 32 bit (xp, vista, 7) địa chỉ ảo có độ dài là 32 bits
-        => Trong window 32 bits thì không gian địa chỉ ảo có địa chỉ từ 0000000h -> 7FFFFFFF

"Pointer in C++" and "Pascal" From basic to advanced - Webzone Tech Tips - Zidane

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;

"Pointer in C++" and "Pascal" From basic to advanced - Webzone Tech Tips - Zidane


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?
     }
     


Khi code trong 1 project lớn. Giả sử bạn có 1 hàm, thao tác với 1 mảng, hàm này chỉ đọc mảng thôi, ko làm thay đổi các giá trị trong mảng . Và quan trọng là, khi share code cho các bạn khác trong cùng project, làm sao để họ biết điều này?

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


"Pointer in C++" and "Pascal" From basic to advanced - Webzone Tech Tips - Zidane


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]

Chú ý : trình biên dịch luôn hiểu a[i] là *(a+i)
-    Các phần tử được sắp xếp liên tiếp trên bộ nhớ => đặc điểm cơ bản của mảng 1 chiều
-    Sử dụng toán tử sizeof đối với mảng trên để trả về kích thước của mảng
-    Chỉ cần 1 con trỏ trỏ vào đầu mảng là ta có thể kiểm soát được cả mảng rồi bằng cách lấy tên mảng + i là độ lệch
-    Việc sử dụng a[i] để kiểm soát cũng chính là +i

Source code 1

// 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();
     } 
     

Source code 2

#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 , '\0' , 0

Các trường hợp bị SAI

Chưa có bộ nhớ đã sử dụng

char *xau;
     gets(xau); 
     

      Code trên vẫn biên dịch được, nhưng khi chạy sẽ sinh ra lỗi run-time, ở 1 số trình biên dịch ngày xưa thì có thể không bị lỗi đâu
       Nhưng sai thì vẫn là sai, code này sai thuộc loại chưa cấp phát

Thay đổi giá trị của một hằng


     char *xau="huuvi168@gmail.com";
      xau[6]='A';
     
     

Explain
vẫn biên dịch được, nhưng khi chạy sẽ sinh ra lỗi run-time, lỗi này là lỗi cố tình thay đổi giá trị của 1 hằng

        Nguyên nhân sâu xa của vấn đề như sau :
Khi khai báo char *xau="huuvi168@gmail.com"; thì bản chất là
+ Trong vùng nhớ data của chương trình sẽ có 1 hằng chuỗi "huuvi168@gmail.com" . (chuỗi chuỗi, đã là hằng thì ko thể bị thay đổi)
+ Cho con trỏ xau trỏ đến đầu của vùng nhớ đó.
Câu lệnh tiếp theo xau[6]='A'; cố tình thay đổi giá trị của hằng, rõ ràng là sinh ra lỗi rồi

Cố tình thay đổi giá trị của hằng con trỏ


     char xau[100];
     xau="Zidane ViLH"; // không biên dịch được
     
     char *xau="huuvi168@gmail.com";
      xau[6]='A';
     
     

Explain   
Vì phép toán trên có nghĩa là khai báo 1 chuỗi "Zidane ViLH" trong vùng nhớ code, rồi sau đó cho hằng con trỏ xâu trỏ vào đó, Rất tiếc xau là hằng con trỏ nên ko thể trỏ đi đâu khác được, ngoài vị trí đã được khởi tạo trong câu lệnh khai báo

Notes
char xau[100]="Zidane ViLH"; hoặc char xau[100]={0}; thì hoàn toàn hợp lệ

Dùng phép toán so sánh để so sánh nội dung 2 xâu


void main()
     {
         char xau[100]="learntechtips";
         if (xau == "learntechtips")
         {
             ... 
         }
        
     }
     

Explain
if (xau == "learntechtips")
=> chỗ này không sai về syntax, ko sinh ra lỗi runtime, nhưng mang lại kết quả ko như người dùng mong muốn, vì như phép toán của con trỏ, ta có Phép so sánh ngang bằng dùng để, kiểm tra 2 con trỏ có trỏ vào cùng 1 vùng nhớ hay không, hoặc kiểm tra 1 con trỏ có phải là đang trỏ vào NULL hay không? chứ ko phải là phép so sánh nội dung của xâu ký tự
Do đó để so sáng nội dung của xâu ta phải dùng những hàm strcmp (string compare) hoặc stricmp hay những hàm tự định nghĩa

Mỗi chương trình thực hiện 1 hàm, 1 khối lệnh thì các đối tượng cục bộ khai báo trong khối hay hàm đó được tổ chức lưu trữ trong ngăn xếp (stack).
Stack phình to ra, nở rộng xuống phía dưới,
khi hàm kết thức, các đối tượng cục bộ được giải phóng, stack nhỏ lại

"Pointer in C++" and "Pascal" From basic to advanced - Webzone Tech Tips - Zidane

10. Dynamically allocated? - Cấp phát động?

Cú pháp C:

-    Dùng malloc, free
contro = (Ép kiểu) malloc ( … )
-    malloc trả về 1 địa chỉ đến 1 vùng nhớ và coi vùng nhớ này là void *, nên trong câu lệnh malloc luôn đi kèm với việc ép kiểu
-    Cấp phát là luôn phải đi kèm với giải phóng, ở đâu cũng thế, malloc là phải free, ok ? Code mà để thoát chương trình rồi chưa giải phóng cho dù là có hệ thống có tự giải phóng đi nữa vẫn bị coi là CODE KHÔNG TỐT !!!!
-    Trong java chỉ cần cho reference = null là nó giải phóng nhưng trong C thì bắt buộc phải có thao tác giải phóng free()

Cú pháp C++:


     -    Dùng new, delete
     int *p = new int();
     delete (p);
     

Cú pháp pascal:


-    Dùng new, dispose
     var intPointer: ^integer;
     new (intPointer);
     dispose(intPoinster);
     
     

Sự khác nhau giữ malloc và new?

-    Malloc là hàm, cấp phát trả về void*,
-    Malloc ko gọi hàm tạo, free không gọi hàm hủy
-    Malloc trả về NULL nếu thất bại

-    New là toán tử, new gọi hàm tạo, new có thể được đa năng hóa (nạp chồng)
-    New ném ra exception nếu thất bại
-    Toán tử new new và toán tử new[] không có khả năng realloc

-    Dùng để cấp phát bộ nhớ to nếu dùng a[1000000] -> không cho cấp phát vì vùng Stack của mỗi chương trình là CÓ giới hạn, vì vậy phải dùng kỹ thuật cấp phát động xem lại Bộ nhớ ảo và Địa chỉ Ảo

11. Con trỏ Hàm


-    Bản chất của con trỏ hàm cũng là 1 con trỏ có định kiểu
-    Sử dụng con trỏ hàm để gọi hàm (invoke) khi biết địa chỉ

Source code - Gọi nội hàm


// https://learn-tech-tips.blogspot.com
     #include <stdio.h>
     #include <conio.h>
     int min(int a,int b)
     {
         if (a>b) return a;
         return b;
     }
     void main()
     {
         int (*p)(int,int);
         p=min;
         printf("min cua 4 va 5 la %d", p(4,5));
         getch();
     }
     

Chú ý:
khi khai báo ta phải dùng toán tử () với ý nghĩa là * này thuộc về p, là 1 con trỏ hàm. int (*p)(int,int);

Source code - Gọi ngoài hàm


void (*p) (int)
     p =   (void (*)(int)) 0x873AB;
     p(3); // gọi hàm với tham số là 3
     
     

12. Hằng con trỏ hàm

Khi khai báo một hàm, tên của hàm chính là hằng con trỏ hàm (con trỏ này cố định vao vùng nhớ của hàm). => hằng con trỏ hàm cũng gần gần giống như khái niệm hằng con trỏ với mảng một chiều

(int) p  = int (main)
     P == (int*)main;
     (int (*)()) p == main;
      P = (void*)main;
     
     

Ứng dụng của con trỏ hàm:

-    Gọi hàm từ chương trình khác, làm auto game võ lâm bấm Ctrl + Z mở hộp thư
-    Nguyên tắc là: dùng kỹ thuật hook để cái 1 Thread vào trong game. Thread này khi người dùng ấn nút Ctrl+Z nó sẽ gọi hàm mở hộp thư ingame

Example:
Giả sử ta có hàm dạng: open(int a) tại địa chỉ 0x007712CE thì để gọi hàm này minh làm:

void (*p) (int);
     p = (void (*) (int)) 0x00712CE;
     p(7);    // gọi hàm với tham số là 7
     
     

Summary

- Miền giá trị của biến con trỏ là địa chỉ ô nhớ

1. p point to a (p trỏ đến a)


"Pointer in C++" and "Pascal" From basic to advanced - Webzone Tech Tips - Zidane


Source code:

int a = 7777;
     int *p;
     P trỏ đến a khi giá trị trong p chứa địa chỉ ảo của a
     

Error


"Pointer in C++" and "Pascal" From basic to advanced - Webzone Tech Tips - Zidane



int a = 7777;
     int *p;
     p = a (or *p = a) -> Không có dấu &
     
     

Như hình trên p trỏ vào 1 ô nhớ mà không hề biết tới. không hề biết rằng ô nhớ này có bộ nhớ vật lý hay chưa, cũng không hề biết rằng nó chứa cái gì trong đấy/ nằm ở vùng nhớ nào

=> Do đó khả năng gây lỗi run-time là vô cùng lớn

2. Nhiều con trỏ cùng trỏ vào một ô nhớ


"Pointer in C++" and "Pascal" From basic to advanced - Webzone Tech Tips - Zidane


Source code:


     int a = 7777;
     int *p, *q;
     p = &a;
     q =  &a; // or q = p;
     
     

-    Tuy Hai biến cùng trỏ đến một địa chỉ ảo thì nó vẫn nằm trong ba biến CON TRỎ khác nhau
-    Do đó khi thay đổi giá trị a từ 7777 sang 8888 thì giá trị của con trỏ p và con trỏ q cũng khác nhau (nhưng địa chỉ của hai con trỏ p, q trỏ tới vẫn giống nhau là 0x00778EA1)

3. Ép kiểu con trỏ


Source code

int *p =  (int *)0x0077EFA1
     char *p = (char*)0x0088ADD3
     
     

Nhưng, con trỏ void thì thoải mái, ép kiểu gì cũng được

void * p = (double *)0x00778BDE
     void * p = (char *)0x00778BDE
     void * p = (int *)0x00778BDE
     
     

4. Tăng giảm con trỏ:


"Pointer in C++" and "Pascal" From basic to advanced - Webzone Tech Tips - Zidane

Source code:


double a = 7777;
     double *p;
     p = &a
     p++ // p = p + 1;
     
     

Do p trỏ đến một biến double nên việc +1 sẽ làm tương ứng với giá trì trong p + 8 đơn vị
Vì sizeof(double) = 8
p = p + 1 <=> 0x00778EA0 + 0x8 = 0x00778EA8
p = p – 1 <=> 0x00778EA0 – 0x8 = 0x00778E98





[Sưu Tầm Internet + sách kỹ thuật lập trình C++/Pascal + Góp ý]


Are you interested in topic "Pointer in C++" and "Pascal" From basic to advanced from Webzone Tech Tips? If you have any thoughts or questions, please share them in the comment section below. I would love to hear from you and chat about it

Webzone Tech Tips Zidane


🙇🏼🙇🏼 Your Feedback Is Valuable and Helpful to Us - Webzone, all things Tech Tips web development Zidane
Popular Webzone Tech Tips topic maybe you will be like it - by Webzone Tech Tips - Zidane
As a student, I found Blogspot very useful when I joined in 2014. I have been a developer for years . To give back and share what I learned, I started Webzone, a blog with tech tips. You can also search for tech tips zidane on Google and find my helpful posts. Love you all,

I am glad you visited my blog. I hope you find it useful for learning tech tips and webzone tricks. If you have any technical issues, feel free to browse my posts and see if they can help you solve them. You can also leave a comment or contact me if you need more assistance. Here is my blog address: https://learn-tech-tips.blogspot.com.

My blog where I share my passion for web development, webzone design, and tech tips. You will find tutorials on how to build websites from scratch, using hot trends frameworks like nestjs, nextjs, cakephp, devops, docker, and more. You will also learn how to fix common bugs on development, like a mini stackoverflow. Plus, you will discover how to easily learn programming languages such as PHP (CAKEPHP, LARAVEL), C#, C++, Web(HTML, CSS, javascript), and other useful things like Office (Excel, Photoshop). I hope you enjoy my blog and find it helpful for your projects. :)

Thanks and Best Regards!
Follow me on Tiktok @learntechtips and send me a direct message. I will be happy to chat with you.
Webzone - Zidane (huuvi168@gmail.com)
I'm developer, I like code, I like to learn new technology and want to be friend with people for learn each other
I'm a developer who loves coding, learning new technologies, and making friends with people who share the same passion. I have been a full stack developer since 2015, with more than years of experience in web development.
Copyright @2022(November) Version 1.0.0 - By Webzone, all things Tech Tips for Web Development Zidane
https://learn-tech-tips.blogspot.com