Lập trình C/C++

Con trỏ hằng và Hằng con trỏ trong C/C++

Con trỏ hằng và Hằng con trỏ trong C/C++
Được viết bởi Minh Hoàng

Series lập trình C/C++, ngôn ngữ lập trình hệ thống mạnh mẽ.

Tiếp tục loạt bài trong series về con trỏ, trong bài này chúng ta sẽ tìm hiểu những nội dung sau:

  1. Hằng con trỏ (Constant pointer) là gì?
  2. Con trỏ hằng (Pointer to constant) là gì?
  3. Hằng con trỏ trỏ tới hằng (Constant pointer to constant) là gì?
1. Hằng con trỏ (Constant pointer) là gì?
1. Hằng con trỏ (Constant pointer) là gì?

■ Khai báo:

<Kiểu dữ liệu> * const <Tên con trỏ> = <Địa chỉ khởi tạo>;

■ Đặc điểm:

  • Khi khai báo hằng con trỏ cần khởi tạo giá trị địa chỉ cho nó.
  • Và từ lúc này, địa chỉ khởi tạo đó là cố định, không bao giờ thay đổi. Tức là: khi hằng con trỏ đã trỏ đến 1 địa chỉ, nó sẽ nằm “dính chặt” vào đó, không thể trỏ tới bất kỳ 1 địa chỉ nào khác.
  • Có thể thay đổi được giá trị tại địa chỉ đã khởi gán ban đầu.

Ví dụ 1: Lỗi khi hằng con trỏ p không được khởi tạo địa chỉ khi khai báo.

[code language=”c”] #include <iostream>

int main()
{
int* const p; // error

return 0;
}
[/code]

Trình biên dịch thông báo lỗi vì hằng con trỏ p không khởi tạo địa chỉ khi khai báo

Trình biên dịch thông báo lỗi vì hằng con trỏ p không khởi tạo địa chỉ khi khai báo

Ví dụ 2: Lỗi khi thay đổi địa chỉ của hằng con trỏ.

[code language=”c” highlight=”6″] #include <iostream>

int main()
{
int m = 2;
int* const p = &m;
p++; // error

return 0;
}
[/code]

Trình biên dịch thông báo lỗi vì hằng con trỏ không thể thay đổi địa chỉ trỏ tới

Trình biên dịch thông báo lỗi vì hằng con trỏ không thể thay đổi địa chỉ trỏ tới

Ví dụ 3: Việc thay đổi giá trị là OK.

[code language=”c” highlight=”7″] #include <stdio.h>

int main()
{
int m = 2;

int* const p = &m;

printf("\n*p = %d", *p);

// Thay đổi giá trị tại biến mà hằng con trỏ trỏ tới
m++; // OK

printf("\n*p = %d", *p);

// Thay đổi giá trị của hằng con trỏ
*p = 9; // OK

printf("\n*p = %d", *p);

getchar();
return 0;
}
[/code]

Thay đổi giá trị của hằng con trỏ là OK

Thay đổi giá trị của hằng con trỏ là OK

Từ đây ta có thể thấy tên mảng 1 chiều chính là một hằng con trỏ. Vì có thể thay đổi giá trị con trỏ arr trỏ tới, nhưng không thể thay đổi giá trị của arr.

int arr[5];
	
arr[0] = 5;		// ok
arr[9] = 1987;	        // ok

arr++;			// lỗi ko thể thay đổi
arr--;			// lỗi ko thể thay đổi
2. Con trỏ hằng (Pointer to constant) là gì?
2. Con trỏ hằng (Pointer to constant) là gì?

■ Khai báo:

const <Kiểu dữ liệu> * <Tên con trỏ>;

■ Đặc điểm:

  • Con trỏ hằng có thể trỏ đến các ô nhớ khác nhau (có thể trỏ đi lung tung trong bộ nhớ, các phép toán tăng giảm địa chỉ của con trỏ hoàn toàn hợp lệ).
  • Nhưng không thể thay đổi giá trị tại ô nhớ mà nó đang trỏ đến.

Có thể bạn quan tâm: Cách cấp phát và giải phóng bộ nhớ trong lập trình C.

* Các bạn có thể nhận thấy nó ngược với hằng con trỏ đã nói ở trên.

* Ví dụ điển hình là hàm strlen mà chúng ta hay sử dụng để lấy chiều dài của một chuỗi:

size_t strlen ( const char * str );

Ví dụ 1: Con trỏ hằng có thể thay đổi địa chỉ mà nó trỏ tới.

[code language=”c” highlight=”9″] #include <stdio.h>

int main()
{
int num1 = 2;
int num2 = 10;
char *blog = "minhhn.com";

const int *p;

p = &num1;
printf("\nGia tri nhan duoc: %d", *p); // Output: 2

p = &num2;
printf("\nGia tri nhan duoc: %d", *p); // Output: 10

p = blog;
printf("\nGia tri nhan duoc: %s", p); // Output: minhhn.com

getchar();
return 0;
}
[/code]

Ví dụ 2: Con trỏ hằng không thể thay đổi giá trị của địa chỉ mà nó trỏ tới.

[code language=”c” highlight=”7″] #include <stdio.h>

int main()
{
int m = 3;

const int *p;

p = &m;

m = 20; // ok
m++; // ok

*p = 99; // error
(*p)++; // error

return 0;
}
[/code]

Khi bạn code trong 1 project C lớn một tí hoặc lớn nhiều tí, 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, không 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:

[code language=”c”] #include <stdio.h>
/*
Đối với trường hợp con trỏ hằng là tham số thì:
void Xuly(const int *) và void Xuly(int const *)
là như nhau, từ const khi đóng góp vào trong tham số hình thức là như nhau.
*/
void Xuly(const int *a, int n)
{
// Xử lý gì đó
}

int main()
{
int a[] = { 1,2 };
int n = 2;

Xuly(a, n); // Khi sử dụng hàm này tôi hiểu là: nó ko thay đổi các giá trị mảng a của tôi đâu
// yên tâm xài, nếu có lỗi gì đó thì ko phải sinh ra từ đây.
return 0;
}
[/code]

3. Hằng con trỏ trỏ tới hằng (Constant pointer to constant) là gì?
3. Hằng con trỏ trỏ tới hằng (Constant pointer to constant) là gì?

■ Khai báo:

const <Kiểu dữ liệu> * const <Tên con trỏ> = <Địa chỉ khởi tạo>;

■ Đặc điểm:

  • Không thể thay đổi được địa chỉ mà con trỏ trỏ tới.
  • Và cũng không thể thay đổi được giá trị tại địa chỉ mà con trỏ trỏ tới.
[code language=”c” highlight=”8″] #include <stdio.h>

int main()
{
int m = 44;
int n = 55;

const int* const p = &m;

p = &n; // error: Không thể thay đổi địa chỉ

*p = 100; // error: Không thể thay đổi giá trị

return 0;
}
[/code]

Cảm ơn bạn đã theo dõi. Đừng ngần ngại hãy cùng thảo luận với chúng tôi!

Giới thiệu

Minh Hoàng

Xin chào, tôi là Hoàng Ngọc Minh, hiện đang làm BrSE, tại công ty Toyota, Nhật Bản. Những gì tôi viết trên blog này là những trải nghiệm thực tế tôi đã đúc rút ra được trong cuộc sống, quá trình học tập và làm việc. Các bài viết được biên tập một cách chi tiết, linh hoạt để giúp bạn đọc có thể tiếp cận một cách dễ dàng nhất. Hi vọng nó sẽ có ích hoặc mang lại một góc nhìn khác cho bạn[...]

2 bình luận

Translate »