Sự khác biệt giữa
char* name
trỏ đến một chuỗi ký tự không đổi và
const char* name
Sự khác biệt giữa
char* name
trỏ đến một chuỗi ký tự không đổi và
const char* name
Câu trả lời:
char*
là một con trỏ có thể thay đổi thành một ký tự / chuỗi có thể thay đổi .
const char*
là một con trỏ có thể thay đổi thành một ký tự / chuỗi bất biến . Bạn không thể thay đổi nội dung của (các) vị trí mà con trỏ này trỏ tới. Ngoài ra, trình biên dịch được yêu cầu đưa ra thông báo lỗi khi bạn cố gắng làm như vậy. Vì lý do tương tự, chuyển đổi từ const char *
sang char*
bị phản đối.
char* const
là một con trỏ bất biến (nó không thể trỏ đến bất kỳ vị trí nào khác) nhưng nội dung của vị trí mà điểm đó có thể thay đổi .
const char* const
là một con trỏ bất biến cho một ký tự / chuỗi bất biến .
char const *
char *
đưa ra lỗi phân khúc trong khi chạy?
const
nếu tôi muốn trình biên dịch báo lỗi nếu tôi quên và thay đổi dữ liệu do nhầm lẫn, phải không?
char *name
Bạn có thể thay đổi char thành name
điểm nào, và cũng là char mà nó trỏ tới.
const char* name
Bạn có thể thay đổi char thành name
điểm nào, nhưng bạn không thể sửa đổi char tại điểm đó.
sửa lỗi: Bạn có thể thay đổi con trỏ, nhưng không thay đổi thành char name
( https://msdn.microsoft.com/en-us/l Library / vstudio / whkd4k6a ( v = vs.100) .aspx , xem "Ví dụ" ). Trong trường hợp này, const
specifier áp dụng cho char
, không phải dấu hoa thị.
Theo trang MSDN và http://en.cppreference.com/w/cpp/lingu/declarations , phần const
trước *
là một phần của trình tự xác định từ chối, trong khi phần const
sau *
là một phần của trình khai báo.
Một trình xác định khai báo có thể được theo sau bởi nhiều khai báo, đó là lý do tại sao const char * c1, c2
khai báo c1
as const char *
và c2
as const char
.
BIÊN TẬP:
Từ các bình luận, câu hỏi của bạn dường như đang hỏi về sự khác biệt giữa hai khai báo khi con trỏ trỏ đến một chuỗi bằng chữ.
Trong trường hợp đó, bạn không nên sửa đổi char thành name
điểm nào, vì nó có thể dẫn đến Hành vi không xác định . Chuỗi ký tự có thể được phân bổ trong các vùng bộ nhớ chỉ đọc (xác định thực hiện) và một chương trình người dùng không nên sửa đổi nó trong bất kỳ cách nào. Bất kỳ nỗ lực để làm như vậy đều dẫn đến Hành vi không xác định.
Vì vậy, sự khác biệt duy nhất trong trường hợp đó (sử dụng với chuỗi ký tự) là khai báo thứ hai mang lại cho bạn một lợi thế nhỏ. Trình biên dịch thường sẽ đưa ra cảnh báo trong trường hợp bạn cố gắng sửa đổi chuỗi ký tự trong trường hợp thứ hai.
#include <string.h>
int main()
{
char *str1 = "string Literal";
const char *str2 = "string Literal";
char source[] = "Sample string";
strcpy(str1,source); //No warning or error, just Undefined Behavior
strcpy(str2,source); //Compiler issues a warning
return 0;
}
Đầu ra:
cc1: cảnh báo đang được coi là lỗi
prog.c: Trong hàm 'main':
prog.c: 9: error: truyền đối số 1 của 'strcpy' loại bỏ vòng loại khỏi loại mục tiêu con trỏ
Lưu ý trình biên dịch cảnh báo cho trường hợp thứ hai nhưng không phải cho trường hợp thứ nhất.
name
điểm trong cả hai trường hợp. Nó có thể dẫn đến UB.
char mystring[101] = "My sample string";
const char * constcharp = mystring; // (1)
char const * charconstp = mystring; // (2) the same as (1)
char * const charpconst = mystring; // (3)
constcharp++; // ok
charconstp++; // ok
charpconst++; // compile error
constcharp[3] = '\0'; // compile error
charconstp[3] = '\0'; // compile error
charpconst[3] = '\0'; // ok
// String literals
char * lcharp = "My string literal";
const char * lconstcharp = "My string literal";
lcharp[0] = 'X'; // Segmentation fault (crash) during run-time
lconstcharp[0] = 'X'; // compile error
// *not* a string literal
const char astr[101] = "My mutable string";
astr[0] = 'X'; // compile error
((char*)astr)[0] = 'X'; // ok
char *
giá trị gây ra lỗi phân đoạn vì chúng tôi đang cố gắng sửa đổi một chuỗi ký tự (hiện diện trong bộ nhớ chỉ đọc)
Trong cả hai trường hợp, bạn không thể sửa đổi một chuỗi ký tự, bất kể con trỏ tới chuỗi ký tự đó được khai báo là char *
hay const char *
.
Tuy nhiên, sự khác biệt là nếu con trỏ là const char *
trình biên dịch phải đưa ra chẩn đoán nếu bạn cố gắng sửa đổi giá trị trỏ, nhưng nếu con trỏ là char *
vậy thì không.
extern ... name
và có *name = 'X';
. Trên 'hệ điều hành phù hợp', điều đó có thể thất bại, nhưng trên các hệ thống nhúng, tôi hy vọng nó sẽ làm một cái gì đó cụ thể cho nền tảng / trình biên dịch.
TRƯỜNG HỢP 1:
char *str = "Hello";
str[0] = 'M' //Warning may be issued by compiler, and will cause segmentation fault upon running the programme
Các tập hợp ở trên str để trỏ đến giá trị bằng chữ "Xin chào" được mã hóa cứng trong hình ảnh nhị phân của chương trình, được gắn cờ là chỉ đọc trong bộ nhớ, có nghĩa là bất kỳ thay đổi nào trong chuỗi ký tự này là bất hợp pháp và điều đó sẽ gây ra lỗi phân đoạn.
TRƯỜNG HỢP 2:
const char *str = "Hello";
str[0] = 'M' //Compile time error
TRƯỜNG HỢP 3:
char str[] = "Hello";
str[0] = 'M'; // legal and change the str = "Mello".
Cái đầu tiên bạn thực sự có thể thay đổi nếu bạn muốn, cái thứ hai bạn không thể. Đọc về const
tính chính xác (có một số hướng dẫn tốt đẹp về sự khác biệt). Cũng có char const * name
nơi bạn không thể từ chối nó.
Câu hỏi là sự khác biệt giữa
char *name
trỏ đến một chuỗi ký tự không đổi và
const char *cname
Tức là đã cho
char *name = "foo";
và
const char *cname = "foo";
Không có nhiều sự khác biệt giữa 2 và cả hai có thể được xem là chính xác. Do di sản dài của mã C, các chuỗi ký tự chuỗi đã có một loại char[]
, không const char[]
, và có rất nhiều mã cũ hơn chấp nhận char *
thay vì const char *
, ngay cả khi chúng không sửa đổi các đối số.
Sự khác biệt chính của 2 nói chung là *cname
hoặc cname[n]
sẽ đánh giá các giá trị của loại const char
, trong khi *name
hoặc name[n]
sẽ đánh giá các giá trị của loại char
, đó là các giá trị có thể sửa đổi . Một trình biên dịch tuân thủ được yêu cầu để tạo ra một thông điệp chẩn đoán nếu mục tiêu của bài tập không phải là một giá trị có thể sửa đổi ; nó không cần tạo ra bất kỳ cảnh báo nào về việc gán giá trị loại char
:
name[0] = 'x'; // no diagnostics *needed*
cname[0] = 'x'; // a conforming compiler *must* produce a diagnostics message
Trình biên dịch không bắt buộc phải dừng quá trình biên dịch trong cả hai trường hợp; nó là đủ để nó tạo ra một cảnh báo cho nhiệm vụ cname[0]
. Chương trình kết quả không phải là một chương trình chính xác . Hành vi của các cấu trúc là không xác định . Nó có thể bị sập, hoặc thậm chí tệ hơn, nó có thể không gặp sự cố và có thể thay đổi chuỗi ký tự trong bộ nhớ.
Thật ra, char* name
không phải là một con trỏ tới một hằng số, mà là một con trỏ tới một biến. Bạn có thể nói về câu hỏi khác này.