2011-09-09 34 views
7

Giả sửTôi tự hỏi điều gì thực sự & lợi nhuận?

Trường hợp đầu tiên

int a; 
int *p= &a ; it works no error 

trường hợp thứ hai

long int a; 
long int b; 
b = & a; it wont work 

Hầu hết chúng ta nói b là một biến không phải là một con trỏ. Nhưng hãy xem bên dưới.

Câu hỏi đặt ra là nếu &a trả lại địa chỉ là số nguyên không dấu thì tại sao chúng ta không thể gán nó vào một biến bình thường? Nhưng tại sao chỉ với con trỏ? Xem bên dưới

b = (unsigned int) &a ; it works after typecasting though its not practicable. 

Nếu địa chỉ là định dạng số nguyên thì tại sao số nguyên không dấu hoặc dài lưu nó? Tôi đã nghĩ, phải có một số bí mật ẩn đằng sau nó. Bất cứ ai có thể tiết lộ nó? Những gì tôi nghĩ là, con trỏ phải làm một cái gì đó bên trong nhưng tôi tự hỏi nó sẽ là gì và tại sao một biến bình thường không thể được.

Cảm ơn tất cả các câu trả lời của bạn nhưng câu hỏi thực sự thực sự là gì trả về &a? Giá trị số nguyên hay không? nếu nó là số nguyên tại sao một biến không thể giữ nó? long int a = 65535 \ hợp lệ tại sao không int a = & b nếu giá trị của địa chỉ b là 65535

Tôi không lo lắng khi sử dụng nó làm con trỏ, hãy đặt câu hỏi là chỉ lưu giá trị. Không trì hoãn địa chỉ. Mọi người nói 32 hoặc 64 bit, tôi không lo lắng về điều đó. Tại sao nó không thể lưu địa chỉ nếu địa chỉ là một số nguyên?

Ý tôi là lý do tại sao không thể chúng ta gán giá trị, tôi không nói với gán các thuộc tính của con trỏ đến biến nhưng chỉ gán giá trị thats nó

a=65535 
b = a \\ works it assigns b - 65535 
&a=65535 
b = & a \\ doesn't work, if address is a some integer value,why we can't store it in a variable? 

lấy chút 16 làm ví dụ con trỏ bình thường (các địa chỉ) là 2 byte và kích thước biến là 2 byte vì sao chúng ta không lưu trữ địa chỉ trong biến khác nếu địa chỉ là giá trị số nguyên mà câu hỏi của tôi tìm thấy nhiều câu trả lời như ++ nó tăng thêm 4 con trỏ và giá trị 1 đến biến, không lo lắng về điều đó chỉ việc gán giá trị là câu hỏi quan trọng hơn.

b = & a ; address of a is 4000 
    ++b ; becomes 4001 thats it,thats not a problem 
+2

Biến "bình thường" là gì? "con trỏ phải làm điều gì đó bên trong" Đúng. Nhiều hơn những gì bạn cần biết? Chúng ** không ** số nguyên. Chúng là con trỏ. Vui lòng ** cập nhật ** câu hỏi của bạn để giải thích ý bạn là "biến thông thường". –

+2

Trong khi đó là một số nguyên bên dưới nắp, các loại không khớp, vì vậy bạn không thể gán chúng. Điều đó giống như nói 'UnrelatedClassA' và 'UnrelatedClassB' chỉ là byte, vậy tại sao bạn không thể gán một cái cho nhau? Đó là một phần của hệ thống kiểu. –

Trả lời

22

Số nguyên, thậm chí long int, không phải lúc nào cũng có cùng kích thước với con trỏ. Đôi khi chúng sẽ là (ví dụ, hầu hết các kiến ​​trúc 32 bit có sizeof(int) == sizeof(void *)), đôi khi chúng sẽ khác nhau (ví dụ, một số kiến ​​trúc 64 bit có sizeof(long) == sizeof(void *) nhưng một số thì không - Visual C++ trên Windows là một ví dụ chính của trình biên dịch nơi sizeof(long) != sizeof(void *)).

Ngoài ra còn có một thực tế rằng void * chỉ đơn giản là không giống nhau loại như long int.

Hãy tưởng tượng một lớp Foo và một lớp Bar, được xác định như sau:

class Foo { 
    public: int a; 
}; 

class Bar { 
    public: int b; 
}; 

Nó giống như hỏi tại sao bạn không thể gán một thể hiện của lớp Foo đến một biến kiểu Bar - họ không điều tương tự, mặc dù trong trường hợp này cả hai FooBar đều có cùng một mẫu bit cơ bản.

+0

Tuyệt vời, @Dean Harding. Đồng bằng tuyệt vời. –

6

Bạn có thể và nó đã rất phổ biến, đó là một vấn đề tính di động thích hợp tại mặc dù là nó không thể được sử dụng trên các nền tảng x64 với một con trỏ 64-bit và 32-bit số nguyên.

Nó có thể bắt nguồn từ việc sử dụng bộ lắp ráp, nơi đăng ký có thể dễ dàng được hiểu là cả số nguyên và con trỏ.

Nó không phải là quá hợp lý trong sử dụng hiện đại vì nó có thể dễ dàng dẫn đến những sai lầm và nhầm lẫn. Loại cải tiến an toàn trong thiết kế trình biên dịch không cho phép sử dụng như vậy nhưng C99 lại giới thiệu một số hỗ trợ tương tự với uintptr_tintptr_t là "Loại nguyên có khả năng giữ đối tượng con trỏ".

Để diễn giải câu hỏi của bạn:

Tại sao chúng ta không thể gán [một con trỏ] tới [một số nguyên] biến?

Câu trả lời là: vì nó không phải là trình biên dịch, C và C++ là strongly typed ngôn ngữ.

3

Nó không dành riêng cho C hoặc C++. Điều này cũng giống nhau ở tất cả các ngôn ngữ được đánh máy mạnh. Đó là một mức độ thậm chí đúng bằng tiếng Anh. Chúng ta có thể nói rằng "màu sắc của cuốn sách là màu xanh", nhưng không phải "màu sắc của cuốn sách là bằng gỗ". A loại hạn chế các giá trị có thể mà một biến có thể có.

Biến số int* chỉ có thể chứa giá trị là địa chỉ của int và biến loại long int chỉ có thể giữ giá trị giữa LONG_MINLONG_MAX bao gồm. Đó chỉ là hai tập hợp giá trị hoàn toàn khác biệt.

C và C++ không tuyệt đối. Typecasting sẽ cho phép bạn bỏ qua một số hạn chế. Ví dụ. (int) 3.5 cho trình biên dịch biết rằng bạn muốn chuyển đổi giá trị số nguyên 3,5 sang giá trị số nguyên xấp xỉ tương tự. Điều này hoạt động tốt hơn nếu hai loại tương tự nhau hơn. Các ngôn ngữ khác có thể không có kiểu gõ như vậy; ở đó bạn có thể cần phải gọi một hàm thay thế. Ví dụ. ROUND(3.5, INT)

+0

'(int) 3.5' ​​là một ví dụ khá xấu vì nó cho thấy một chuyển đổi thay vì một diễn viên. Nếu nó là một dàn diễn viên thực, giá trị sẽ không phải là '3' nhưng bất kể việc giải thích chuỗi bit là gì. – blubb

+0

@Simon: Trong C++, đó là một diễn viên rõ ràng. Một 'static_cast ', chính xác. Nó cũng là một sự biến đổi; cả hai không độc quyền. Dường như bạn đang nghĩ đến một 'reinterpret_cast', là một trong các loại diễn viên khác. Tuy nhiên, bạn không thể 'reinterpret_cast (3.5)'; 'double' to' int' không có trong danh sách các chuyển đổi có thể. (§ 5.2.10) – MSalters

7

trả về địa chỉ đó là một số nguyên unsigned

Không, nó không phải là. Một con trỏ (địa chỉ) là một con trỏ. Giai đoạn.

+0

Mặc dù những gì bạn đang nói là trong thực tế đúng, điều này không thực sự hữu ích cho một newbie con trỏ, mà tôi giả định OP là. – MGZero

+0

MGZero - Tôi đánh giá cao rằng anh ấy * nghĩ * về vấn đề này, và tôi chỉ cho anh ta các bước mà anh ta giả định sai. Tôi tin rằng anh ấy có thể giải quyết vấn đề bằng cách suy nghĩ thêm. Đây là IMHO tốt hơn là để có được tất cả mọi thứ phục vụ trên một máy tính bảng bạc. – Ingo

2

Niko, IMHO điểm của ngôn ngữ đã nhập là bạn không thể chỉ gán một thứ cho người khác, mặc dù chúng chỉ là một loạt các bit ở mức thấp nhất.

1

Con trỏ thường được triển khai dưới dạng số nguyên, nhưng đặc điểm kỹ thuật C++ chỉ xác định hành vi của chúng (vị trí bằng hoặc hai con trỏ khác nhau, v.v.).

Biến một con trỏ thành một uint giống như chuyển đổi một thể hiện của một số loại/loại khác.

Về lý do tại sao b = (uint) &a; hoạt động, có thể tùy thuộc vào việc triển khai. (Và phụ thuộc vào vòm).

2

nếu địa chỉ là định dạng số nguyên thì tại sao không giữ nguyên hoặc dài số nguyên lưu. Tôi đã suy nghĩ, phải có một số bí mật ẩn đằng sau nó.

Địa chỉ không phải là số nguyên; đó là một địa chỉ. Trên một hệ thống 64 bit, điều này:

int *p; 

phân bổ một biến 64 bit, trong khi điều này:

int b; 

phân bổ một biến 32 bit. Chúng không giống nhau. Chúng có thể có cùng kích cỡ trên một số hệ thống, nhưng chúng không giống nhau. Hãy xem xét chỉ là một ví dụ toán tử ++. Trên một hệ thống 32 bit, ++ trên một con trỏ tăng con trỏ lên 4, trong khi ++ trên một số nguyên tăng số nguyên bằng 1. Trình biên dịch đang cố gắng giúp bạn bằng cách nói cho bạn biết bạn đang làm điều gì sai.

1

Từ những gì tôi nhận được trong câu hỏi của bạn, bạn đang ở dưới ấn tượng rằng bởi vì một địa chỉ được biểu diễn dưới dạng hex, đó là một số nguyên. Vâng, chắc chắn, nhưng điều đó không có nghĩa là bạn có thể đặt một số nguyên vào một con trỏ theo cách bạn đang suy nghĩ.

Dữ liệu (biến) có thông tin với dữ liệu ..mã. Kích thước của nó, giá trị, datatype .... địa chỉ nơi nó được lưu trữ. Một con trỏ đang giữ phần cuối cùng của dữ liệu meta, địa chỉ. Nó là một kiểu dữ liệu đặc biệt mà công việc chính là giữ địa chỉ. Giá trị của con trỏ độc lập với giá trị của dữ liệu, chúng là 2 thứ riêng biệt. Giá trị của con trỏ cho bạn biết nơi tìm dữ liệu bạn đang tìm kiếm. Đây là lý do tại sao bạn không thể đặt một số nguyên vào một con trỏ theo cách bạn đang cố gắng. Nó giống như nói rằng bạn sống ở một số địa chỉ đường phố, và bạn cũng là địa chỉ đó. Hãy tưởng tượng nếu mọi người gọi bạn bằng địa chỉ của bạn, điều đó sẽ là ngớ ngẩn!

Hãy xem xét điều này: Bạn có một lớp được gọi là x, chứa một số thành viên. Bạn tạo một con trỏ tới lớp này. Con trỏ vẫn giữ một địa chỉ với một định dạng hex .. nhưng đối tượng không thể được chia thành một giá trị 4 hoặc 8 byte (32 bit và 64 bit tương ứng)! Lưu ý, định dạng của con trỏ trên tất cả các kiểu dữ liệu là như nhau, bất kể giá trị của chúng.

int a; int *p= &a; 

Bây giờ .. lý do tại sao điều này làm việc là vì bạn lấy địa chỉ biến a và đặt nó vào con trỏ p. Từ khóa là ADDRESS, đó là những gì con trỏ giữ.

long int a; 
long int b; 
b = & a; 

Điều này không có tác dụng vì bạn đã thử đặt ADDRESS (con trỏ) của a vào b, mà chỉ là một biến.

Để đơn giản, bạn không thể đặt địa chỉ vào biến thông thường. Một địa chỉ chỉ có thể được lưu trữ trong một con trỏ.

0

Có một quan niệm sai lầm trong tư duy tích cực của bạn: có "biến bình thường" và "người viết bài". Không có khái niệm như vậy. Chỉ có "biến" và "loại".

  • int là một "container cho một giá trị số nguyên"
  • lớp Person là một container cho một mô tả Người.
  • int * là vùng chứa cho địa chỉ của số nguyên
  • Person * là vùng chứa cho địa chỉ của một Người.

Toán tử & trả về địa chỉ của một biến và loại của nó là "con trỏ đến loại đó". Bài tập chỉ có thể đi từ một biểu thức của một kiểu nhất định đến một biến của một kiểu tương thích. int, int *, Person và Person * đều không tương thích với nhau. Bạn không thể gán một int * cho một int vì cùng một lý do bạn không thể gán một Person cho int hoặc int cho một Person. Trừ khi bạn có một hàm cho phép bạn viết một biểu thức trả về một kiểu từ một kiểu khác. giống như operator & và biểu thức &a mang lại cho bạn.

Các vấn đề liên quan