2009-06-18 31 views
42

Tôi đang thử tay mình tại khóa học iPhone từ Stanford trên iTunes U và tôi hơi bối rối về con trỏ. Trong nhiệm vụ đầu tiên, tôi đã cố gắng làm một cái gì đó như thế nàyTại sao tôi không khai báo NSInteger với số *

NSString *processName = [[NSProcessInfo processInfo] processName]; 
NSInteger *processID = [[NSProcessInfo processInfo] processIdentifier]; 

nào tạo ra một lỗi, sau tinkeing xung quanh một cách mù quáng, tôi phát hiện ra rằng đó là * trong dòng NSInteger đã gây ra vấn đề.

Vì vậy, tôi rõ ràng là không hiểu điều gì đang xảy ra. Tôi sẽ giải thích làm thế nào tôi nghĩ rằng nó hoạt động và có lẽ ai đó sẽ được loại, đủ để chỉ ra lỗ hổng.

Không giống như trong quá trình phát triển web, bây giờ tôi cần để lo lắng về bộ nhớ, tốt hơn nhiều so với phát triển web. Vì vậy, khi tôi tạo một biến, nó được phân bổ một bit của bộ nhớ ở đâu đó (RAM I giả định). Thay vì chuyển biến số xung quanh, tôi chuyển một con trỏ tới bit đó của bộ nhớ xung quanh. Và con trỏ được khai báo bằng cách đặt trước tên biến số với *.

Giả sử tôi đúng, câu hỏi của tôi là lý do tại sao tôi không cần phải làm điều đó cho NSInteger?

Trả lời

68

NSInteger là loại nguyên thủy, có nghĩa là có thể được lưu trữ cục bộ trên ngăn xếp. Bạn không cần phải sử dụng một con trỏ để truy cập nó, nhưng bạn có thể nếu bạn muốn. Dòng:

NSInteger *processID = [[NSProcessInfo processInfo] processIdentifier]; 

trả về biến thực tế chứ không phải địa chỉ của nó. Để sửa lỗi này, bạn cần phải loại bỏ các *:

NSInteger processID = [[NSProcessInfo processInfo] processIdentifier]; 

Bạn có thể có một con trỏ đến một NSInteger nếu bạn thực sự muốn một:

NSInteger *pointerToProcessID = &processID; 

dấu và là địa chỉ của nhà điều hành. Nó đặt con trỏ đến số NSInteger bằng với địa chỉ của biến trong bộ nhớ, chứ không phải là số nguyên trong biến.

+0

Tôi nghi ngờ đó sẽ là một mẹo rất tiện dụng. Cảm ơn. – gargantuan

+2

Đó là một bản ghi nhớ lớn đối với tôi khi tôi chuyển từ phát triển webdev sang iPhone. Một trong những khác để xem ra cho là chắc chắn để chấm dứt NSArray với nil. –

+3

Nếu bạn nhấn đúp chuột vào NSInteger hoặc các loại khác bạn đang nhầm lẫn trong XCode, bạn có thể được đưa đến định nghĩa của nó, trong trường hợp này sẽ là: typedef int NSInteger; Vì vậy, đó là một int cũ đơn giản sau khi tất cả. –

25

Lý do bạn không khai báo NSInteger với * là vì nó không phải là một đối tượng. Một NSInteger chỉ đơn giản là một int hay long:

#if __LP64__ 
typedef long NSInteger; 
#else 
typedef int NSInteger; 
endif 

Nếu nó đang được sử dụng trong một ứng dụng 32-bit, đó là một 32-bit số nguyên, và nếu nó được xây dựng trong một ứng dụng 64-bit, đó là một 64 số nguyên-bit.

Tất nhiên, bạn có thể chuyển số NSInteger làm con trỏ, nhưng hầu hết các hàm chỉ cần lấy đối số dưới dạng NSInteger và không trỏ đến đối số.

Đối tượng, mặt khác, chỉ có thể được truyền cho các chức năng khác dưới dạng con trỏ. Điều này là do các đối tượng có bộ nhớ được cấp phát động cho chúng và do đó không thể được khai báo trên ngăn xếp. Vì số int hoặc long có số lượng bộ nhớ cố định được phân bổ cho chúng, đây không phải là vấn đề.

2

NSInteger chỉ là typedef cho int, AFAIK.

+1

Nó có thể được, nhưng không phải là ở khắp mọi nơi. Trên hệ thống Mac OS X 64 bit, 'NSInteger' được định nghĩa là' long'. Nó không khó để tưởng tượng rằng điều này có thể đúng trên một kiến ​​trúc chạy iOS một ngày nào đó. –

3

* có nghĩa là "con trỏ". Biến đối tượng giữ một con trỏ trỏ đến một đối tượng, vì vậy nó có một *; biến NSInteger giữ một NSInteger, không phải là một con trỏ tới một NSInteger, do đó nó không có một *. Đặt * vào biến đó sẽ cho bạn ít nhất một cảnh báo vì bạn đang đặt một số nguyên vào một biến con trỏ.

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