01/10/2018, 08:19

Về khác biệt của biến con trỏ trong C

Mọi người cho em hỏi là lợi thế của việc dùng con trỏ là như thế nào, một ví dụ đơn giản mà dùng con trỏ thì công việc sẽ thuận lợi hơn không ạ, em tham khảo tài liệu và diễn đàn nhưng chưa thực sự hiểu về nó, về khái niệm nôm na thì mọi người có thể nói cho em con trỏ dùng để làm gì không ạ.

Tao Không Ngu. viết 10:34 ngày 01/10/2018

Hi Hung Pham Hoang.
Dùng con trỏ không đem lại cho bạ lợi thế gì cả.
Vì thế nên không có ví dụ nào cho bạn. @@!
Vậy tại sao lại cần nó ? Vì nó là 1 phần của máy tính người ta không cần nó mà nó tự sinh ra.
Vấn đề là ngôn ngữ có cung cấp cho bạn cách để dùng nó hay không thôi.
Hahahaha @
@!

Nguyễn Duy Hùng viết 10:30 ngày 01/10/2018

Một ví dụ đó là cấp phát động vùng nhớ cho mảng. nếu như khai báo một mảng int a[1000*1000] là bị tràn stack ngay, nhưng nếu như int *a = new int[1000*1000] ( trong C là dùng malloc ) thì sẽ không có gì vì khi đó con trỏ *a đang quản lý vùng nhớ đầu tiên trong một triệu ô nhớ tiếp sau nó trong heap, chỉ cần *(a+i) là lấy được giá trị của ô thứ i-1 @@. Trong C++ thì nó có cấu trúc vector để khắc phục hạn chế của mảng. Con trỏ theo mình nghĩ nó dùng để quản lý địa chỉ vùng nhớ, còn làm gì với nó thì tùy .

Hung Pham Hoang viết 10:34 ngày 01/10/2018

mình thấy trong C các thầy cô vẫn hay dùng con trỏ đó ạ.

Hung Pham Hoang viết 10:30 ngày 01/10/2018

cảm ơn bạn, mình đã hiểu ví dụ bạn nói rồi. Chắc phải qua nhiều ví dụ mình mới biết cách sử dụng, thấy m.n xung quanh sử dụng mà ko hiểu sao phải dùng

rogp10 viết 10:34 ngày 01/10/2018
  • Viết thẳng lên 1 vùng chỉ định (cực hiếm, h chắc chỉ có hx0r mới viết ntn). Cast 1 con số thành con trỏ rồi ghi vào.
  • Do một con trỏ có thể đại diện cho cả 1 vùng nhớ nên khi sử dụng vùng nhớ ta chỉ cần con trỏ và kích cỡ của nó.
  • Pass by reference
  • Con trỏ có thể trỏ đến 1 double hay 1 int nên 1 số trick lấy nó làm trung gian (Fast Inverse Square Root). Ví dụ như int b = *(int*) &f; float g = *(float*) &b;

Nếu viết bt thì khi b=1234 g sẽ là 1234.0 nhưng ở đây g sẽ là gì

Hung Pham Hoang viết 10:21 ngày 01/10/2018

ok, mình hiểu rồi, tks bạn

明玉 viết 10:26 ngày 01/10/2018

Cho bạn một ví dụ về đọc byte, không có con trỏ thì làm cũng được mà chậm hơn, code rối hơn, nếu bạn lập trình convert file này sang file nọ, đọc data từ file nhị phân, bạn sẽ tầm quan trọng của con trỏ:

char a[4]; // chuỗi gồm 4 phần tử liên tiếp, được thể hiện dạng hex: 0F FF 22 33
a[0] = 0x0F; // Nhóm 1
a[1] = 0xFF; // Nhóm 1
a[2] = 0x22; // Nhóm 2
a[3] = 0x33; // Nhóm 2

// biết rằng 2 byte đầu và 2 byte cuối đều là thể hiện số 16 bit little endian
// vậy:
// muốn lấy 2 byte đầu tiên:
short b = *(short*)a; // 0xFF0F
// muốn lấy 2 byte cuối:
short c = *(short*)(a + 2); // 0x3322
// dữ liệu thực tế có thể lớn hơn nhiều, cái này mà code bằng C# chắc khóc mất

Công nghệ lập trình do con người làm ra, cái gì cũng có chỗ của nó cả.

Còn nếu mục tiêu của bạn là làm web, lập trình dịch vụ thì thôi.

Nguyen Trong Dung viết 10:28 ngày 01/10/2018

b đang học những tài liệu hay web nào vậy ?
mình cũng đang học con trỏ của C, bạn share mình với

Hung Pham Hoang viết 10:23 ngày 01/10/2018

hi, mình học tùm lum lắm, học qua C rồi mà vẫn chưa thực sự hiểu về con trỏ
Tài liệu thì bạn có thể tham khảo ở đây https://discuss.eggclub.org/t/tai-li-u-h-c-t-p-va-chia-s-ki-n-th-c-v-c/182

Nguyen Trong Dung viết 10:23 ngày 01/10/2018

mình cũng học qua r, mà giờ vẫn đang học con trỏ ^^!

Nguyễn Hồng Hải viết 10:28 ngày 01/10/2018

ví dụ so sánh với array thì linked list cơ động hơn vì có thể thêm bớt phần tử để tối ưu bộ nhớ (không bị thừa hay thiếu) chẳng hạn

rogp10 viết 10:34 ngày 01/10/2018

Bạn có thể viết thêm struct mới cho array nó tự co giãn được

Nguyễn Quốc Hoàng viết 10:26 ngày 01/10/2018

Bạn không xứng đáng với cái tên “Tao Không Ngu”, con trỏ dùng để tạo mảng cấp phát động, lấy dữ liệu ở Heap, tuy việc này chậm hơn nhưng có lợi thế là tiết kiệm dữ liệu
Ngoài mục đích cấp phát động thì nó còn dùng để làm tham số truyền vào cho các biến có kiểu dữ liệu lớn như struct, danh sách liên kết, …
Nó còn được dùng làm biến đầu ra trong các chương trình con nữa

Hung Pham Hoang viết 10:32 ngày 01/10/2018

Ví dụ của biến đầu ra dùng con trỏ là như nào nhỉ @@

Nguyễn Xuân Phúc viết 10:30 ngày 01/10/2018

Bạn nên bỏ chữ “Khong” trong tên của bạn đi là vừa
Không phải vô duyên vô cớ mà nhiều người nói “muốn master C thì phải master pointer” đâu nhé

  • Với mảng kích thước lớn, stack sẽ bị giới hạn (nếu khai báo kiểu int thì khoảng 108 là sẽ bị chặn stack ngay) như heap thì lại khác
  • Tùy chính được kích thước dữ liệu trong lúc thao tác, đây cũng là cơ chế mà thằng std::vector dùng để cấp phát mảng cho nó (nó cấp phát theo kiểu nhân đôi, ban đầu cấp 1, sau đó cấp 2, luôn giữ kích thước mảng là dạng 2k vì vậy nên độ phức tạp của vector trung bình khi thêm và truy xuất phần tử trong vector mới là O(1))
  • Các cấu trúc như Linked List, Tree, … không có con trỏ thì sống sao, nếu không nhờ con trỏ thì thằng C++ cũng không có được mấy thằng map, set, priority_queue hiệu quả như vậy để dev dùng đâu
  • Không có con trỏ thì lấy đâu ra con trỏ hàm, không có con trỏ hàm thì lấy đâu ra các hàm sort cho ta khả năng thay đổi độ ưu tiên sắp xếp (ví dụ dễ thấy nhất). Mà không có nó thì còn lâu mới dùng được cá hàm sort hay compare để mà dùng?
Tao Không Ngu. viết 10:23 ngày 01/10/2018

Hi Nguyễn Quốc Hoàng.
1 Cảm ơn vì bạn đã nghĩ thế.
2 Những gì bạn nói là đúng.
3 Vấn đề là C không cung cấp những công cụ mạnh hơn để làm những việc đó.(Các ngôn ngữ không có con trỏ vẫn làm tốt những việc đó và ít nhầm lẫn hơn.)
4 Việc dùng con trỏ giống như việc bạn cưa một quả bom vậy. Có thể thành anh hùng cũng có thể thành kẻ tội đồ.
5 Việc dùng làm biến đầu ra trong các trương trình con cần xem xét kỹ.

Tao Không Ngu. viết 10:29 ngày 01/10/2018

Hi Nguyễn Xuân Phúc.
1 Tên mình đặt chỉ là theo câu nói này thôi “Không sợ những thằng ngu tỏ ra nguy hiểm mà chỉ sợ những thằng nguy hiểm giả vờ ngu”
2 Những gì bạn nói hoàn toàn đúng.
3 Vấn đề là C không cung cấp những công cụ mạnh hơn để làm những việc đó.(Các ngôn ngữ không có con trỏ vẫn làm tốt những việc đó và ít nhầm lẫn hơn.)
4 Bạn đã khi nào liệt kê các vấn đề mà con trỏ gây ra khi code chưa ?
5 Làm việc vói con trỏ cũng giống như bạn là root vậy. Bạn có nhiều quyền thật dấy nhưng đi kèm với nó là bạn có nhiều trách nhiệm phải chịu.(Không phải tự nhiên Ubuntu bỏ root và thay bằng sudo).

Nguyễn Xuân Phúc viết 10:30 ngày 01/10/2018

Chính vì việc nó khó, dễ gây lỗi nếu không kiểm soát kỹ, nên mới có cái câu muốn master C thì phải master pointer đó thôi.
(3) Đúng là có những ngôn ngữ khác không có con trỏ, và nó vẫn làm được, nhưng tốc độ có bằng C? Nhiều ngôn ngữ không có pointer, nhưng bù lại nó phải có cơ chế kiểm soát scope cũng như lifetime của các biến, đối tượng, thì nó ngược lại giảm hiệu năng. Đó là vấn đề, bạn muốn tốc độ cao, hiệu năng tốt, đòi hỏi bạn phải đánh đổi.
(4), (5) Việc kiểm soát con trỏ đòi hỏi level cao đối với C, vậy chẳng lẽ vì nó khó, nó rối, nó dễ lỗi (mà lỗi là do mình kiểm soát không được), là mình tìm cách thoái thác? Có thể bạn không làm việc với C mà 1 ngôn ngữ nào đó k có con trỏ, thì bạn thấy nó vô dụng, nhưng giả sử bạn sử dụng C là ngôn ngữ lập trình của mình và dùng nó để làm việc như một bộ phận dev, thì liệu rằng có nơi nào chấp nhận việc bạn làm việc với C mà lại không biết gì về con trỏ?
Bạn gặp vấn đề với con trỏ, không thể kiểm soát con trỏ, không đồng nghĩa với việc con trỏ có vấn đề và không thể kiểm soát được.

Tao Không Ngu. viết 10:29 ngày 01/10/2018

Hi Nguyễn Xuân Phúc.
Cảm ơn bạn nhiều,

Nguyễn Quốc Hoàng viết 10:34 ngày 01/10/2018

Được cái này thì mất cái kia thôi, nếu như được cái an toàn thì sẽ hi sinh tốc độ dịch và chạy chương trình
ASM là một ví dụ

Bài liên quan
0