Làm thế nào để khởi tạo giá trị “int * ptr = int ()” không bất hợp pháp?


86

Đoạn mã sau (lấy từ đây ):

int* ptr = int();

biên dịch trong Visual C ++ và khởi tạo giá trị con trỏ.

Làm thế nào là có thể? Ý tôi là int()tạo ra một đối tượng kiểu intvà tôi không thể gán intmột con trỏ.

Làm thế nào là đoạn mã trên không bất hợp pháp?


Không phải là một câu trả lời, mà là một câu hỏi tuyệt vời! Tôi chưa bao giờ thấy một điều như vậy.
Josh

6
Vì các nguyên thủy có một 'hàm tạo' trong C ++, int()mang lại giá trị được xây dựng bằng giá trị int(tôi nghĩ là một thứ được chỉ định trong C ++ 03) và giá trị mặc định int0. Điều này tương đương vớiint *ptr = 0;
wkl

7
@EmanuelEy: Không, bất kỳ hằng số nguyên nào có giá trị bằng 0 đều có thể được sử dụng làm hằng số con trỏ null, bất kể con trỏ thực sự được triển khai như thế nào.
Mike Seymour

1
@MooingDuck: Tôi không nói NULLcó thể là giá trị khác 0. Tôi đã nói nó có thể là bất kỳ hằng số nguyên nào có giá trị bằng 0 (bao gồm int()).
Mike Seymour

5
@DanielPryden Đó là cách sử dụng từ "đối tượng" mà trước đây tôi không biết.
mịn

Câu trả lời:


110

int()là một biểu thức hằng có giá trị 0, vì vậy đó là một cách hợp lệ để tạo ra hằng số con trỏ null. Cuối cùng, đó chỉ là một cách nói hơi khácint *ptr = NULL;


3
+1, bit biểu thức hằng là quan trọng và bị thiếu trong 2 câu trả lời được ủng hộ hàng đầu.
David Rodríguez - dribeas

điều này có biến mất với C ++ 0x không?
Neil G

@NeilG: Điều này vẫn giữ nguyên trong C ++ 11, mặc dù bây giờ cũng có một nullptr, mà bạn có thể sử dụng thay thế 0hoặc NULLtrong mã mới.
Jerry Coffin, 9/11/11

2
@Nils: Mã rõ ràng và tuyên bố ý định của bạn thông qua mã. Tất nhiên, với C ++ 11, bây giờ bạn muốn sử dụng nullptr vì nó cũng đưa lợi ích của việc kiểm tra thời gian biên dịch bổ sung vào hỗn hợp.
Jamin Grey

3
@Nils vì rõ ràng 0có thể có nghĩa là hằng số con trỏ null hoặc số 0, trong khi nullptrhiển nhiên là hằng số con trỏ null. Ngoài ra, như Jamin đã nói, nó cũng có "kiểm tra thời gian biên dịch bổ sung". Cố gắng suy nghĩ trước khi nhập.
Miles Rout

35

Bởi vì int()sản lượng 0, có thể hoán đổi cho nhau NULL. NULLchính nó được định nghĩa là 0, không giống như C NULL(void *) 0.

Lưu ý rằng đây sẽ là một lỗi:

int* ptr = int(5);

và điều này sẽ vẫn hoạt động:

int* ptr = int(0);

0là một giá trị hằng số đặc biệt và như vậy nó có thể được coi như một giá trị con trỏ. Các biểu thức hằng mang lại 0, chẳng hạn như 1 - 1được phép cũng như hằng số con trỏ null.


1
Cũng lưu ý rằng C's NULL cũng không nhất thiết (void *)0. Nó chỉ đơn giản là một triển khai được định nghĩa "biểu thức hằng số nguyên với giá trị 0 hoặc một biểu thức như vậy được ép kiểu void *".
Jerry Coffin,

@JerryCoffin Tôi chưa bao giờ sử dụng trình biên dịch C được định nghĩa NULL(void*)0; nó luôn luôn 0(hoặc có thể 0L). (Nhưng sau đó, vào thời điểm C90 trở thành (void*)0hợp pháp bằng C, tôi đã sử dụng C ++.)
James Kanze 9/11/11

1
@JamesKanze: Trong ubuntu 11.04 và hương vị linux của riêng chúng tôi, libio.h chứa: #if !defined(__cplusplus) \n #define NULL ((void*)0) \n #else \n #define NULL (0)phiên bản hiện tại của gcc trong ubuntu là 4.5, trong hệ thống của chúng tôi là 4.0.
David Rodríguez - dribeas

5
" 0là một ký tự đặc biệt" - chỉ vì nó là một biểu thức hằng và nó có giá trị đặc biệt (1-1)là 0. cũng đặc biệt không kém, nó cũng là một hằng con trỏ null, và như vậy int(). Thực tế 0là một nghĩa đen là điều kiện đủ nhưng không cần thiết để trở thành một biểu thức hằng. Một cái gì đó như strlen(""), mặc dù nó cũng có giá trị đặc biệt 0, nhưng không phải là một biểu thức hằng và do đó không phải là một hằng con trỏ null.
Steve Jessop

@SteveJessop: Tôi đồng ý về việc điều chỉnh, đó thực sự là về giá trị không đổi 0, không phải 0nghĩa đen.
Blagovest Buyukliev

18

Biểu thức int()đánh giá là một số nguyên được khởi tạo mặc định không đổi, giá trị này là 0. Giá trị đó đặc biệt: nó được sử dụng để khởi tạo một con trỏ đến trạng thái NULL.


2
Điều này còn thiếu một chi tiết rất quan trọng có trong câu trả lời của Jerry: biểu thức mang lại giá trị 0 là chưa đủ, mà nó còn phải là một biểu thức hằng . Đối với một ví dụ ngược lại, với int f() { return 0; }, biểu thức f()mang lại giá trị 0, nhưng nó không thể được sử dụng để khởi tạo một con trỏ.
David Rodríguez - dribeas

@ DavidRodríguez-dribeas, trong lúc gấp rút trình bày câu trả lời bằng những thuật ngữ đơn giản nhất có thể, tôi đã bỏ qua phần đó. Tôi hy vọng nó có thể chấp nhận được bây giờ.
Mark Ransom

13

Từ n3290 (C ++ 03 sử dụng văn bản tương tự), 4.10 Chuyển đổi con trỏ [ch.ptr] đoạn 1 (phần nhấn mạnh là của tôi):

1 Hằng số con trỏ null là một hằng số tích phân biểu thức (5.19) prvalue của kiểu số nguyên có giá trị bằng 0 hoặc prvalue kiểu std :: nullptr_t. Hằng số con trỏ null có thể được chuyển đổi thành kiểu con trỏ; kết quả là giá trị con trỏ null của kiểu đó và có thể phân biệt được với mọi giá trị khác của kiểu con trỏ đối tượng hoặc con trỏ hàm. Chuyển đổi như vậy được gọi là chuyển đổi con trỏ null. [...]

int()là một biểu thức hằng số tích phân prvalue của kiểu số nguyên có giá trị bằng 0 (thật lạ!), và do đó có thể được sử dụng để khởi tạo một kiểu con trỏ. Như bạn có thể thấy, 0không phải là biểu thức tích phân duy nhất được đặt dấu nghiêng đặc biệt.


4

Cũng int không phải là một đối tượng.

Tôi tin rằng những gì đang xảy ra ở đây là bạn đang nói với int * trỏ đến một số địa chỉ bộ nhớ được xác định bởi int ()

vì vậy nếu int () tạo 0, int * sẽ trỏ đến địa chỉ bộ nhớ 0


1
int()chắc chắn nhất một đối tượng.
Các cuộc đua ánh sáng trong quỹ đạo vào

@Tomalak: Tôi không nghĩ là như vậy. Đó là tạm thời của kiểu không phải lớp và tôi nghĩ tôi đúng khi nói rằng đây không phải là các đối tượng theo như tiêu chuẩn C ++ có liên quan. Tuy nhiên, hơi kỳ lạ, phần "đối tượng tạm thời" bắt đầu cẩn thận chỉ nói về thời gian tạm thời của loại lớp, nhưng sau đó nó nói về các tham chiếu ràng buộc và tất nhiên bạn có thể liên kết một tham chiếu với int(). Xác định int i;, sau đó không có câu hỏi, ilà một đối tượng.
Steve Jessop

@Steve: Tôi chỉ mong đợi cuộc tranh luận về điều này ở chỗ "các đối tượng" là một vùng lưu trữ trong C ++ và các vùng tạm thời không thực sự có bộ nhớ, phải không? 1.8 / 1 không liệt kê rõ ràng các khoảng thời gian tạm thời, nhưng có vẻ như có ý định bao gồm chúng.
Lightness Races in Orbit,

1
@Tomalak: đúng vậy, các tệp tạm thời thuộc loại không phải lớp không cần lưu trữ trừ khi bạn tham khảo. Đừng bận tâm, nó không quan trọng lắm. Câu lệnh "well int không phải là một đối tượng" chỉ đúng vì intlà một kiểu chứ không phải một đối tượng. Cho dù int()mang lại một đối tượng hay chỉ một giá trị không ảnh hưởng đến bất cứ điều gì mà bất cứ ai đã nói ở nơi khác.
Steve Jessop

@Steve: Bấy nhiêu là không thể tắm được :)
Lightness Races in Orbit.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.