Hỏi/ Thắc mắc - Kiểu dữ liệu con trỏ char? | VN-Zoom | Cộng đồng Chia Sẻ Kiến Thức Công Nghệ và Phần Mềm Máy Tính

Adblocker detected! Please consider reading this notice.

We've detected that you are using AdBlock Plus or some other adblocking software which is preventing the page from fully loading.

We need money to operate the site, and almost all of it comes from our online advertising.

If possible, please support us by clicking on the advertisements.

Please add vn-z.vn to your ad blocking whitelist or disable your adblocking software.

×

Hỏi/ Thắc mắc Kiểu dữ liệu con trỏ char?

boyfriend

Búa Gỗ Đôi
Xin chào mọi người.
Hôm nay thì mình vẫn đang học đệ quy, nhưng biết là đang thủng cái chuỗi kí tự, nên mới đi học chuỗi kí tự, mà học chuỗi kí tự nó lại đâm sang con trỏ hôm trước. Con trỏ sau khi mọi người góp ý thì mình hiểu cũng được kha khá rồi. Tuy nhiên, mình đọc dòng này, ở trang daynhauhoc, gặp một dòng khá khó hiểu.
1585833813587.png


Tức là khi khai báo một biến con trỏ để lưu chuỗi. Thì khi dùng lệnh cout, với cú pháp <tên biến con trỏ> thì theo lẽ thường nó sẽ in cái địa chỉ của biến mà nó lưu giữ. Đằng này nó in ra nội dung của biến. Mà mình đọc thì chưa rõ cho lắm là lý do tại sao như thế? Có phải là do kiểu char không cho phép xuất địa chỉ của biến hay không?

Mong các bạn giúp mình.
Cám ơn các bạn.
Link mình đọc: https://cpp.daynhauhoc.com/8/3-con-tr-va-mang-ki-tu/
@dammage @binhbro @tramanh89xd @BinhHT
 

nhoxboy2010

Rìu Sắt Đôi
Theo link bạn đưa, có đoạn này "Thực ra đối tượng cout chỉ hổ trợ cho kiểu con trỏ char (char *)" và "mảng truyền qua hàm thì suy biến thành con trỏ (tức là mất luôn sizeof), nên tham số là char[] hay char* đều có tác dụng như nhau."

Nếu bạn muốn in địa chỉ của biến kiểu char, thì có thể ép kiểu về pointer để làm điều đó.
Vd:
C++:
char ch = 'a';
std::cout << (void*)(&ch) << std::endl;
 

boyfriend

Búa Gỗ Đôi
Theo link bạn đưa, có đoạn này "Thực ra đối tượng cout chỉ hổ trợ cho kiểu con trỏ char (char *)" và "mảng truyền qua hàm thì suy biến thành con trỏ (tức là mất luôn sizeof), nên tham số là char[] hay char* đều có tác dụng như nhau."

Nếu bạn muốn in địa chỉ của biến kiểu char, thì có thể ép kiểu về pointer để làm điều đó.
Vd:
C++:
char ch = 'a';
std::cout << (void*)(&ch) << std::endl;
Tức là nó như nhau hả bạn.
Mình nhớ cái char * là kiểu const tức là không thể thay đổi được kí tự bên trong. Nhưng char[] thì khác.
Với lại cái máy mình, chẳng biết sao VS19 nó không cho phép sử dụng kiểu pointer nhỉ

1585837585290.png
 

nhoxboy2010

Rìu Sắt Đôi
(char *) không phải là constant đâu.
Còn lỗi bạn gặp là do vi phạm standard của C++11. Bạn không thể truyền 1 chuỗi (constant) vào 1 pointer char * theo cách thông thường được mà phải ép kiểu thành constant pointer.
C++:
char *p_str = "abc"; //Vi phạm C++11 standard
constant char *p_str = "abc"; //OK
 

boyfriend

Búa Gỗ Đôi
(char *) không phải là constant đâu.
Còn lỗi bạn gặp là do vi phạm standard của C++11. Bạn không thể truyền 1 chuỗi (constant) vào 1 pointer char * theo cách thông thường được mà phải ép kiểu thành constant pointer.
C++:
char *p_str = "abc"; //Vi phạm C++11 standard
constant char *p_str = "abc"; //OK
Wao, cảm ơn bạn nhiều nhé
 

dammage

Rìu Chiến
cái này chắc phải nói dài lắm, rất dễ, nhưng dài


<--------------<>-<< 1 >>-<>-------------->​


con trỏ trong c nếu kết hợp với từ khóa const thì có 2 cách kết hợp
1/const nằm bên trái dấu * gọi là con trỏ hằng: không cho phép thay đổi dữ liệu thông qua con trỏ đó
2/const nằm bên phải dấu * gọi là hằng con trỏ: không cho phép con trỏ đó trỏ qua nơi khác

con trỏ hằng có thể trỏ tới biến hằng hoặc biến thường, nhưng con trỏ thường chỉ có thể trỏ tới biến thường mà thôi
Untitled.jpg

nói 1 cách hình tượng thì cũng giống như cái nồi lớn có thể nấu được 1 con gà hoặc 1 con chim cút, nhưng cái nồi nhỏ thì chỉ có thể nấu được cút mà thôi, lý do có cái quy tắc này đơn giản là để ngăn không cho thay đổi giá trị của biến hằng thông qua con trỏ bình thường


<--------------<>-<< 2 >>-<>-------------->​


giờ nói về mảng trong c, giả sử cho 1 mảng a
int a[100];

thì khi làm việc với biến a, thực chất là bạn đang làm việc với địa chỉ của phần tử đầu tiên trong mảng a, chẳng hạn
int *p = a;
tương đương với
int *p = &a[0];

khi truyền cho hàm cũng vậy
strlen(a);
tương đương với
strlen(&a[0]);

như vậy 3 dòng sau đây tất cả đều là 1
strlen(a);
strlen(p);
strlen(&a[0]);

<--------------<>-<< 3 >>-<>-------------->​

giờ nói về chuỗi, chuỗi kí tự trong c thực chất chỉ là 1 mảng char, với kí tự cuối cùng phải là NULL hoặc 0 hoặc '\0'

các chuỗi nằm trong cặp ngoặc kép như
char *p = "dammage";
printf("this is sparta");
gọi là các chuỗi hằng, nó có kiểu ngầm định là const char [] nên bạn không thể lấy con trỏ thường mà trỏ tới nó được (như giải thích ở < 1 >)
const char *p = "dammage";

nhưng viết như thế này thì được
char a[100] = "dammage";
char a[] = "dammage";

đối tượng cout của lớp ostream đã có quá tải toán tử <<, mà về hình thức thì quá tải toán tử cũng giống như hàm thôi, mà như hàm thì đã giải thích ở < 2 >, bởi vậy 3 cái dưới đây là như nhau
cout << str << p_str << &str[0];
 
Sửa lần cuối:

boyfriend

Búa Gỗ Đôi
cái này chắc phải nói dài lắm, rất dễ, nhưng dài


<--------------<>-<< 1 >>-<>-------------->​


con trỏ trong c nếu kết hợp với từ khóa const thì có 2 cách kết hợp
1/const nằm bên trái dấu * gọi là con trỏ hằng: không cho phép thay đổi dữ liệu thông qua con trỏ đó
2/const nằm bên phải dấu * gọi là hằng con trỏ: không cho phép con trỏ đó trỏ qua nơi khác

con trỏ hằng có thể trỏ tới biến hằng hoặc biến thường, nhưng con trỏ thường chỉ có thể trỏ tới biến thường mà thôi
Untitled.jpg

nói 1 cách hình tượng thì cũng giống như cái nồi lớn có thể nấu được 1 con gà hoặc 1 con chim cút, nhưng cái nồi nhỏ thì chỉ có thể nấu được cút mà thôi, lý do có cái quy tắc này đơn giản là để ngăn không cho thay đổi giá trị của biến hằng thông qua con trỏ bình thường


<--------------<>-<< 2 >>-<>-------------->​


giờ nói về mảng trong c, giả sử cho 1 mảng a
int a[100];

thì khi làm việc với biến a, thực chất là bạn đang làm việc với địa chỉ của phần tử đầu tiên trong mảng a, chẳng hạn
int *p = a;
tương đương với
int *p = &a[0];

khi truyền cho hàm cũng vậy
strlen(a);
tương đương với
strlen(&a[0]);

như vậy 3 dòng sau đây tất cả đều là 1
strlen(a);
strlen(p);
strlen(&a[0]);

<--------------<>-<< 3 >>-<>-------------->​

giờ nói về chuỗi, chuỗi kí tự trong c thực chất chỉ là 1 mảng char, với kí tự cuối cùng phải là NULL hoặc 0 hoặc '\0'

các chuỗi nằm trong cặp ngoặc kép như
char *p = "dammage";
printf("this is sparta");
gọi là các chuỗi hằng, nó có kiểu ngầm định là const char [] nên bạn không thể lấy con trỏ thường mà trỏ tới nó được (như giải thích ở < 1 >)
const char *p = "dammage";

nhưng viết như thế này thì được
char a[100] = "dammage";
char a[] = "dammage";

đối tượng cout của lớp ostream đã có quá tải toán tử <<, mà về hình thức thì quá tải toán tử cũng giống như hàm thôi, mà như hàm thì đã giải thích ở < 2 >, bởi vậy 3 cái dưới đây là như nhau
cout << str << p_str << &str[0];
Cảm ơn bạn rất nhiều, mình mới vừa ôn lại con trỏ hằng xong, đọc lại của bạn thì hiểu ra vấn đề. Cám ơn bạn nhiều, bạn nói dễ hiểu quá
 


Top