Sự khác biệt giữa:
char * const
và
const char *
Sự khác biệt giữa:
char * const
và
const char *
Câu trả lời:
Sự khác biệt là const char *
một con trỏ đến a const char
, trong khi char * const
là một con trỏ không đổi đến a char
.
Đầu tiên, giá trị được trỏ đến không thể thay đổi nhưng con trỏ có thể. Thứ hai, giá trị được trỏ vào có thể thay đổi nhưng con trỏ không thể (tương tự như tham chiếu).
Cũng có một
const char * const
đó là một con trỏ liên tục đến một char không đổi (vì vậy không có gì có thể thay đổi).
Ghi chú:
Hai hình thức sau là tương đương:
const char *
và
char const *
Lý do chính xác cho điều này được mô tả trong tiêu chuẩn C ++, nhưng điều quan trọng cần lưu ý và tránh nhầm lẫn. Tôi biết một số tiêu chuẩn mã hóa thích:
char const
kết thúc
const char
(có hoặc không có con trỏ) sao cho vị trí của const
phần tử giống như với con trỏ const
.
const int *foo,*bar;
sẽ tuyên bố cả hai foo
và bar
được int const *
, nhưng int const *foo, *bar
sẽ tuyên bố foo
là một int const *
và bar
được int *
. Tôi nghĩ rằng typedef int * intptr; const intptr foo,bar;
sẽ khai báo cả hai biến là int * const
; Tôi không biết cách nào để sử dụng khai báo kết hợp để tạo hai biến loại đó mà không cần typedef.
I believe const int *foo,*bar; would declare both foo and bar to be int const *
: Vâng. but int const *foo, *bar would declare foo to be a int const * and bar to be int *
: Không! Nó sẽ giống hệt như trường hợp trước. (Xem ideone.com/RsaB7n nơi bạn gặp cùng một lỗi cho cả foo và bar). I think typedef int * intptr; const intptr foo,bar; would declare both variables to be int * const
: Đúng. I don't know any way to use a combined declaration to create two variables of that type without a typedef
: Vâng , int *const foo, *const bar;
. Cú pháp khai báo C ...
int const *foo, *volatile bar
làm gì bar
? Làm cho cả hai const
và volatile
? Tôi nhớ rằng việc phân tách rõ ràng các tên biến khai báo của Pascal và các kiểu của chúng (một con trỏ tới một mảng các con trỏ tới các số nguyên sẽ là var foo: ^Array[3..4] of ^Integer
: `. Đó sẽ là một số dấu ngoặc đơn được lồng vào nhau trong C, tôi nghĩ vậy
int const *foo, *volatile bar
" phần loại là int const
(dừng trước *
) và người khai báo là *foo
(biểu thức *foo
sẽ biểu thị một int const
) và *volatile bar
; đọc từ phải sang trái (quy tắc tốt cho vòng loại cv ), foo
là con trỏ tới const int và bar
là con trỏ dễ bay hơi cho const int (chính con trỏ dễ bay hơi, int nhọn được [truy cập là] const).
[3..4]
cú pháp, vì vậy hãy lấy một mảng gồm 10 phần tử) : int *(*foo)[10];
. Nó phản ánh (sử dụng trong tương lai) của nó như là một biểu thức: *(*foo)[i]
(với i
một số nguyên trong phạm vi [0, 10)
tức là [0, 9]
) sẽ lần đầu tiên foo
nhận được tại mảng, sau đó truy cập vào phần tử tại chỉ mục i
(vì hậu []
tố liên kết chặt chẽ hơn tiền tố *
), sau đó cuối cùng là phần tử này mang lại một int
(xem ideone.com/jgjIjR ). Nhưng typedef
làm cho nó dễ dàng hơn (xem ideone.com/O3wb7d ).
Để tránh nhầm lẫn, luôn luôn nối thêm vòng loại const.
int * mutable_pointer_to_mutable_int;
int const * mutable_pointer_to_constant_int;
int *const constant_pointer_to_mutable_int;
int const *const constant_pointer_to_constant_int;
p
không liên quan đến loại : (const int *const)
. Cho tốt hơn hoặc tồi tệ hơn (tệ hơn nếu bạn hỏi tôi) vòng loại const, cả trong C và C ++, có nghĩa là postfix: hàm cf const thành viên void foo(int a) const;
. Khả năng khai báo const int
là ngoại lệ chứ không phải là quy tắc.
const
luôn luôn sửa đổi thứ xuất hiện trước nó (ở bên trái của nó), NGOẠI TRỪ khi đó là điều đầu tiên trong một khai báo kiểu, trong đó nó sửa đổi điều xuất hiện sau nó (bên phải của nó).
Vì vậy, hai cái này giống nhau:
int const *i1;
const int *i2;
họ định nghĩa con trỏ tới a const int
. Bạn có thể thay đổi vị trí i1
và i2
điểm, nhưng bạn không thể thay đổi giá trị mà chúng trỏ đến.
Điều này:
int *const i3 = (int*) 0x12345678;
xác định một const
con trỏ tới một số nguyên và khởi tạo nó để trỏ đến vị trí bộ nhớ 12345678. Bạn có thể thay đổi int
giá trị tại địa chỉ 12345678, nhưng bạn không thể thay đổi địa chỉ i3
trỏ đến.
const * char
là mã C không hợp lệ và là vô nghĩa. Có lẽ bạn muốn hỏi sự khác biệt giữa a const char *
và a char const *
, hoặc có thể là sự khác biệt giữa a const char *
và a char * const
?
const char*
là một con trỏ tới một ký tự không đổi
char* const
là một con trỏ không đổi cho một ký tự
const char* const
là một con trỏ không đổi đến một ký tự không đổi
Nguyên tắc nhỏ: đọc định nghĩa từ phải sang trái!
const int *foo;
Có nghĩa là " foo
điểm ( *
) đến mức int
không thể thay đổi ( const
)".
Đối với lập trình viên, điều này có nghĩa là "Tôi sẽ không thay đổi giá trị của những gì foo
trỏ đến".
*foo = 123;
hoặc foo[0] = 123;
sẽ không hợp lệ.foo = &bar;
được cho phép.int *const foo;
Có nghĩa là " foo
không thể thay đổi ( const
) và điểm ( *
) thành một int
".
Để các lập trình viên phương tiện này "Tôi sẽ không thay đổi địa chỉ bộ nhớ mà foo
đề cập đến".
*foo = 123;
hoặc foo[0] = 123;
được cho phép.foo = &bar;
sẽ không hợp lệconst int *const foo;
Có nghĩa là " foo
không thể thay đổi ( const
) và điểm ( *
) thành int
không thể thay đổi ( const
)".
Để các lập trình viên phương tiện này "Tôi sẽ không thay đổi giá trị của những gì foo
điểm đến, cũng không phải tôi sẽ thay đổi địa chỉ đó foo
đề cập đến".
*foo = 123;
hoặc foo[0] = 123;
sẽ không hợp lệ.foo = &bar;
sẽ không hợp lệconst char * x Ở đây X về cơ bản là một con trỏ ký tự đang trỏ đến một giá trị không đổi
char * const x được dùng để chỉ con trỏ ký tự không đổi, nhưng vị trí nó đang trỏ có thể thay đổi.
const char * const x được kết hợp thành 1 và 2, có nghĩa là nó là một con trỏ ký tự không đổi được trỏ đến giá trị không đổi.
const * char x sẽ gây ra lỗi trình biên dịch. nó không thể được tuyên bố.
char const * x bằng điểm 1.
quy tắc của ngón tay cái là nếu const có tên var thì con trỏ sẽ không đổi nhưng vị trí trỏ có thể thay đổi , con trỏ khác sẽ trỏ đến một vị trí không đổi và con trỏ có thể trỏ đến một vị trí khác nhưng nội dung vị trí trỏ không thể thay đổi .
Rất nhiều câu trả lời cung cấp các kỹ thuật cụ thể, quy tắc ngón tay cái, vv để hiểu trường hợp cụ thể này của khai báo biến. Nhưng có một kỹ thuật chung để hiểu bất kỳ tuyên bố nào:
Quy tắc theo chiều kim đồng hồ / xoắn ốc
A)
const char *a;
Theo quy tắc theo chiều kim đồng hồ / xoắn ốc a
là con trỏ đến ký tự không đổi. Có nghĩa là ký tự không đổi nhưng con trỏ có thể thay đổi. tức a = "other string";
là ổn nhưng a[2] = 'c';
sẽ không biên dịch
B)
char * const a;
Theo quy tắc, a
là con trỏ const cho một ký tự. tức là bạn có thể làm a[2] = 'c';
nhưng bạn không thể làma = "other string";
Tôi đoán bạn có nghĩa là const char * và char * const.
Đầu tiên, const char *, là một con trỏ tới một ký tự không đổi. Các con trỏ chính nó là có thể thay đổi.
Thứ hai, char * const là một con trỏ không đổi cho một ký tự. Con trỏ không thể thay đổi, ký tự mà nó trỏ tới có thể.
Và sau đó là const char * const nơi con trỏ và ký tự không thể thay đổi.
Dưới đây là một lời giải thích chi tiết với mã
/*const char * p;
char * const p;
const char * const p;*/ // these are the three conditions,
// const char *p;const char * const p; pointer value cannot be changed
// char * const p; pointer address cannot be changed
// const char * const p; both cannot be changed.
#include<stdio.h>
/*int main()
{
const char * p; // value cannot be changed
char z;
//*p = 'c'; // this will not work
p = &z;
printf(" %c\n",*p);
return 0;
}*/
/*int main()
{
char * const p; // address cannot be changed
char z;
*p = 'c';
//p = &z; // this will not work
printf(" %c\n",*p);
return 0;
}*/
/*int main()
{
const char * const p; // both address and value cannot be changed
char z;
*p = 'c'; // this will not work
p = &z; // this will not work
printf(" %c\n",*p);
return 0;
}*/
// Some more complex constant variable/pointer declaration.
// Observing cases when we get error and warning would help
// understanding it better.
int main(void)
{
char ca1[10]= "aaaa"; // char array 1
char ca2[10]= "bbbb"; // char array 2
char *pca1= ca1;
char *pca2= ca2;
char const *ccs= pca1;
char * const csc= pca2;
ccs[1]='m'; // Bad - error: assignment of read-only location ‘*(ccs + 1u)’
ccs= csc; // Good
csc[1]='n'; // Good
csc= ccs; // Bad - error: assignment of read-only variable ‘csc’
char const **ccss= &ccs; // Good
char const **ccss1= &csc; // Bad - warning: initialization from incompatible pointer type
char * const *cscs= &csc; // Good
char * const *cscs1= &ccs; // Bad - warning: initialization from incompatible pointer type
char ** const cssc= &pca1; // Good
char ** const cssc1= &ccs; // Bad - warning: initialization from incompatible pointer type
char ** const cssc2= &csc; // Bad - warning: initialization discards ‘const’
// qualifier from pointer target type
*ccss[1]= 'x'; // Bad - error: assignment of read-only location ‘**(ccss + 8u)’
*ccss= ccs; // Good
*ccss= csc; // Good
ccss= ccss1; // Good
ccss= cscs; // Bad - warning: assignment from incompatible pointer type
*cscs[1]= 'y'; // Good
*cscs= ccs; // Bad - error: assignment of read-only location ‘*cscs’
*cscs= csc; // Bad - error: assignment of read-only location ‘*cscs’
cscs= cscs1; // Good
cscs= cssc; // Good
*cssc[1]= 'z'; // Good
*cssc= ccs; // Bad - warning: assignment discards ‘const’
// qualifier from pointer target type
*cssc= csc; // Good
*cssc= pca2; // Good
cssc= ccss; // Bad - error: assignment of read-only variable ‘cssc’
cssc= cscs; // Bad - error: assignment of read-only variable ‘cssc’
cssc= cssc1; // Bad - error: assignment of read-only variable ‘cssc’
}
Cú pháp:
datatype *const var;
char *const
đến trong trường hợp này.
/*program to illustrate the behaviour of constant pointer */
#include<stdio.h>
int main(){
int a=10;
int *const ptr=&a;
*ptr=100;/* we can change the value of object but we cannot point it to another variable.suppose another variable int b=20; and ptr=&b; gives you error*/
printf("%d",*ptr);
return 0;
}
Cú pháp:
const datatype *var
hoặc là datatype const *var
const char*
đến trong trường hợp này.
/* program to illustrate the behavior of pointer to a constant*/
#include<stdio.h>
int main(){
int a=10,b=20;
int const *ptr=&a;
printf("%d\n",*ptr);
/* *ptr=100 is not possible i.e we cannot change the value of the object pointed by the pointer*/
ptr=&b;
printf("%d",*ptr);
/*we can point it to another object*/
return 0;
}
char * const và const char *?
const char * p;
// giá trị không thể thay đổi
char * const p;
// địa chỉ không thể thay đổi
const char * const p;
// cả hai không thể thay đổi.
Công cụ const
sửa đổi được áp dụng cho thuật ngữ ngay bên trái của nó. Ngoại lệ duy nhất này là khi không có gì ở bên trái của nó, sau đó nó áp dụng cho những gì ngay bên phải của nó.
Đây là tất cả các cách tương đương để nói "con trỏ không đổi đến hằng số char
":
const char * const
const char const *
char const * const
char const const *
Hai quy tắc
If const is between char and *, it will affect the left one.
If const is not between char and *, it will affect the nearest one.
ví dụ
char const *. This is a pointer points to a constant char.
char * const. This is a constant pointer points to a char.
Tôi muốn chỉ ra rằng việc sử dụng int const *
(hoặc const int *
) không phải là về một con trỏ trỏ đến một const int
biến, mà là biến này const
dành cho con trỏ cụ thể này.
Ví dụ:
int var = 10;
int const * _p = &var;
Các mã trên biên dịch hoàn toàn tốt. _p
chỉ đến một const
biến, mặc dù var
bản thân nó không phải là hằng số.
Tôi nhớ từ cuốn sách tiếng Séc về C: đọc phần khai báo rằng bạn bắt đầu với biến và rẽ trái. Vì vậy đối với
char * const a;
bạn có thể đọc là: " a
là biến của kiểu con trỏ không đổi char
",
char const * a;
bạn có thể đọc là: " a
là một con trỏ tới biến hằng của kiểu char. Tôi hy vọng điều này có ích.
Tặng kem:
const char * const a;
Bạn sẽ đọc như a
là con trỏ không đổi đến biến hằng của kiểu char.