Trong C++, như trong C, tham số được khai báo kiểu mảng là được điều chỉnh (tại thời gian biên dịch) thành loại con trỏ, cụ thể là con trỏ đến loại phần tử của mảng.
Điều này xảy ra cho dù loại mảng được chỉ định trực tiếp hoặc thông qua typedef (hãy nhớ rằng typedef không tạo loại mới, chỉ là bí danh cho loại hiện có).
Vì vậy, đây:
typedef char ar[];
typedef char* pr;
void f2(ar x, pr y)
{
// ...
}
thực sự có nghĩa là:
void f2(char* x, char* y)
{
// ...
}
Một quy tắc, cũng chia sẻ bởi C và C++, đó là một biểu kiểu mảng là, trong hầu hết nhưng không phải tất cả các ngữ cảnh, được ngầm định chuyển đổi thành con trỏ thành phần tử đầu tiên của đối tượng mảng. Điều đó có nghĩa rằng nếu bạn xác định một đối tượng mảng:
char arr[10];
bạn có thể sử dụng tên của đối tượng đó như một cuộc tranh cãi với một chức năng mà phải mất một tham số char*
(mà mất các giới hạn thông tin).
Trong C, các trường hợp chuyển đổi ngầm này không xảy ra là:
- Khi biểu thức mảng là các toán hạng của
sizeof
(sizeof arr
mang lại kích thước của mảng, không phải là kích thước của một con trỏ);
- Khi biểu thức mảng là toán hạng của đơn nhất
&
(&arr
là một con trỏ tới mảng, không phải là con trỏ đến con trỏ); và
- Khi biểu thức mảng là một chuỗi ký tự được sử dụng để khởi tạo một đối tượng kiểu mảng (
char s[] = "hello";
khởi tạo s
làm mảng, không phải là con trỏ).
Không ai trong số những trường hợp này (hoặc các trường hợp khác xảy ra trong C++) xuất hiện trong chương trình của bạn, vì vậy cuộc gọi của bạn:
f2(data,ptr);
qua hai giá trị con trỏ kiểu char*
-f2
.
Bên f2
, tham số đối tượng x
và y
đều là kiểu char*
, vì vậy std::is_same<decltype(x), decltype(y)>::value
là đúng.
Nhưng các loại ar
và pr
là khác biệt. ar
là loại mảng không đầy đủ char[]
và pr
là loại con trỏ char*
.
Điều này giải thích kết quả của chương trình của bạn. Sự kỳ quặc xảy ra vì tham số x
, mà bạn đã xác định với loại mảng ar
, thực sự thuộc loại char*
, cùng loại với pr
.
Phân hủy? (như tham số chức năng) – dyp
(Tham gia vào bình luận của tôi :) Các kiểu tham số của hàm được "phân rã" theo [dcl.fct]/5: "Sau khi xác định kiểu của mỗi tham số, bất kỳ tham số nào kiểu" mảng của ' T' ”hoặc“ hàm trả về 'T'” được điều chỉnh thành “con trỏ tới' T' ”hoặc“ con trỏ tới hàm trả về 'T'”, tương ứng ”. Do đó 'decltype (x)' là * trỏ tới 'char' *, không * mảng không xác định ràng buộc của' char' * (không giống 'ar'). – dyp
@DyP Cảm ơn bạn đã tham khảo tiêu chuẩn, thưa sếp. – WhozCraig