2010-08-19 29 views
26

thể Duplicates:
Can the Size of Pointers Vary Depending on what’s Pointed To?
Are there are any platforms where pointers to different types have different sizes?Kích thước của con trỏ có thay đổi theo C không?

Có thể rằng kích thước của một con trỏ đến một phao trong c khác với một con trỏ đến int? Đã thử nó, tôi nhận được kết quả tương tự cho tất cả các loại con trỏ.

#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
    printf("sizeof(int*): %i\n", sizeof(int*)); 
    printf("sizeof(float*): %i\n", sizeof(float*)); 
    printf("sizeof(void*): %i\n", sizeof(void*)); 
    return 0; 
} 

Những kết quả đầu ra ở đây (OSX 10,6 64bit)

sizeof(int*): 8 
sizeof(float*): 8 
sizeof(void*): 8 

Tôi có thể giả thiết rằng con trỏ của các loại khác nhau có cùng kích thước (trên một vòm dĩ nhiên)?

+0

dupe? http://stackoverflow.com/questions/1473935/can-the-size-of-pointers-vary-depending-on-whats-pointed-to –

+1

và câu trả lời là "không" –

+1

@kotlinski: có hai boolean câu hỏi: tiêu đề một (chúng khác nhau?) và cái cuối cùng (chúng giống nhau không?). Bạn đang trả lời ai? – MSalters

Trả lời

0

Con trỏ là địa chỉ bộ nhớ - và do đó phải giống nhau trên một máy cụ thể. Máy 32 bit => 4Bytes, 64 bit => 8 Byte.

Do đó không quan tâm đến kiểu dữ liệu mà con trỏ trỏ tới, kích thước của con trỏ trên một máy cụ thể sẽ giống nhau (vì không gian cần lưu trữ địa chỉ bộ nhớ sẽ giống nhau.)

Giả sử: Tôi đang nói về các con trỏ gần với các giá trị dữ liệu, loại bạn đã khai báo trong câu hỏi của bạn.

+5

-1, sai. Đối với người mới bắt đầu nó giả định con trỏ trỏ đến dữ liệu (và một kiểu dữ liệu) mà bỏ qua các con trỏ hàm. Và C trên DOS có một mô hình bộ nhớ với các con trỏ hàm 16 bit và các con trỏ dữ liệu 20/32 bit. – MSalters

+0

Vâng tôi quên thêm 'cho tất cả các mục đích thực tế' vào câu trả lời. Về mặt kỹ thuật, câu trả lời có thể sai - C/C++ luôn có ngoại lệ đối với quy tắc. Tuy nhiên, từ bối cảnh được OP đưa ra trong câu hỏi (vì tôi chỉ đang nghĩ đến các con trỏ gần (bình thường), tôi đoán nó sẽ trả lời anh ta. Cảm ơn vì đã giúp tôi quay lại và đọc lên! – Gishu

0

Con trỏ luôn có cùng kích thước trên cùng một vòm, bất kể kiểu dữ liệu trỏ đến. Nếu không, những thứ như đúc giữa các loại con trỏ khác nhau sẽ vô dụng và phá vỡ nhiều thứ.

Nhiều kỹ thuật mã hóa phổ biến phụ thuộc vào việc truyền giữa ví dụ một con trỏ trống (hoặc một char) cho các cấu trúc khác nhau, tùy thuộc vào kích thước.

Lấy ngay cả printf chuẩn(), phải có khả năng đưa con trỏ đến các loại dữ liệu khác nhau. Nếu con trỏ có kích thước khác nhau, việc triển khai printf có thể rất lộn xộn.

+0

không cần thiết. Việc đúc có thể hoạt động và địa chỉ bộ nhớ thuộc nhiều loại khác nhau, miễn là thông tin "bỏ lỡ" được giữ ở đâu đó trong ngữ cảnh. Trong x86 ngày cũ, loại thông tin này thường là "phân khúc" hiện tại. – kriss

+0

printf đã lấy đối số của các kích thước khác nhau - 'int',' long long' và 'double' không giống nhau. Varargs xử lý này. Không có lý do varargs không thể xử lý tương tự đối số con trỏ của các kích cỡ khác nhau, miễn là hàm đọc varargs xác định chính xác kiểu của mỗi cái khi nó đọc nó. Đây là lý do tại sao macro 'va_arg' lấy một kiểu làm tham số. –

3

Có, kích thước của con trỏ phụ thuộc vào nền tảng. Cụ thể hơn, kích thước của một con trỏ phụ thuộc vào kiến ​​trúc bộ xử lý đích và "bit-ness" mà bạn biên dịch.

Theo quy tắc chung, trên máy 64 bit, con trỏ thường là 64 bit, trên máy 32 bit thường là 32 bit. Tuy nhiên có những trường hợp ngoại lệ.

Vì con trỏ chỉ là một địa chỉ bộ nhớ, nó luôn luôn có cùng kích thước bất kể bộ nhớ mà nó trỏ đến chứa. Vì vậy, một con trỏ đến một phao, một char hoặc một int là tất cả cùng kích thước.

+4

Aehm đây không phải là câu hỏi, câu hỏi là liệu con trỏ đến các kiểu khác nhau (float *, int *, void *) có thể có các kích cỡ khác nhau (trên cùng một nền tảng), không phải là trường hợp. – Nils

+0

+1 Có, trong cửa sổ 16-bit cổ đại ở đó gần (16 bit) và con trỏ xa (32 bit) tùy thuộc vào bộ nhớ và cách sử dụng. – stacker

20

Con trỏ không phải lúc nào cũng có cùng kích thước trên cùng một vòm.

Bạn có thể đọc thêm về khái niệm "gần", "xa" và con trỏ "khổng lồ", cũng giống như một ví dụ về một trường hợp kích thước con trỏ khác nhau ...

http://en.wikipedia.org/wiki/Intel_Memory_Model#Pointer_sizes

+2

Người ta có thể tranh luận, rằng những gì bạn mô tả không phải là "C". Nhưng kể từ khi DOS từng cai trị trái đất và là tiêu chuẩn thực tế, tôi đã cho bạn một cuộc bỏ phiếu. –

+0

Có nhưng cũng trong trường hợp này loại không có ảnh hưởng đến kích thước? – Nils

+0

Nó có thể khác nhau bởi vì các loại khác nhau có thể được đặt trong các phân đoạn bộ nhớ khác nhau. –

11

Trong ngày cũ, sử dụng ví dụ Các trình biên dịch Borland C trên nền tảng DOS, có tổng cộng (tôi nghĩ) 5 mô hình bộ nhớ mà thậm chí có thể được trộn lẫn ở một mức độ nào đó.Về cơ bản, bạn có lựa chọn con trỏ nhỏ hoặc lớn cho dữ liệu, và con trỏ nhỏ hoặc lớn để mã hóa, và một mô hình "nhỏ" trong đó mã và dữ liệu có không gian địa chỉ chung (Nếu tôi nhớ chính xác) 64K.

Có thể chỉ định con trỏ "rất lớn" trong một chương trình được xây dựng theo cách khác trong mô hình "nhỏ". Vì vậy, trong trường hợp xấu nhất có thể có các con trỏ có kích thước khác nhau cho cùng một kiểu dữ liệu trong cùng một chương trình!

Tôi nghĩ tiêu chuẩn này thậm chí không cấm điều này, vì vậy về mặt lý thuyết một trình biên dịch C tối nghĩa có thể làm điều này ngay cả ngày hôm nay. Nhưng có những chuyên gia không chắc chắn sẽ có thể xác nhận hoặc sửa lỗi này.

+0

Tiêu chuẩn không cấm hoàn toàn, nhưng các chi tiết cụ thể không đạt tiêu chuẩn.Tuy nhiên, bạn chỉ ra một cách chính xác rằng bạn có thể lựa chọn độc lập giữa các con trỏ nhỏ và lớn cho mã và dữ liệu. – MSalters

9

Các con trỏ đến dữ liệu phải luôn tương thích với void* vì vậy thông thường chúng sẽ được hiện thực hóa dưới dạng các loại có cùng chiều rộng.

Tuyên bố này không đúng đối với các con trỏ hàm, chúng có thể có chiều rộng khác nhau. Vì lý do đó trong con trỏ chức năng đúc C99 đến void* là hành vi không xác định.

+2

Tất cả điều đó có nghĩa là 'void *' phải có ít nhất kích thước của loại con trỏ lớn nhất khác. – caf

+0

@caf: bạn có thể có nghĩa là "con trỏ khác với kiểu dữ liệu" và "chiều rộng" thay vì "kích thước", vâng tôi nghĩ đây là những gì tôi đã nói trong đoạn đầu tiên của mình. Điều đó không buộc các kiểu dữ liệu con trỏ khác có cùng chiều rộng, nhưng nó rất có khả năng, vì việc truyền lại từ 'void *' vẫn phải có tất cả thông tin để xử lý đối tượng. Nhưng bạn là đúng, một kiến ​​trúc giả thuyết có thể lưu byte thứ tự thấp của các con trỏ cho tất cả các kiểu dữ liệu được căn chỉnh ở ranh giới 256 byte ;-) –

+2

Chính xác - chuyển đổi từ 'void *' sang 'double *' có thể bị mất, nhưng không ngược lại. – caf

4

Vì tôi hiểu không có gì trong tiêu chuẩn C đảm bảo rằng con trỏ đến các loại khác nhau phải có cùng kích thước, do đó, về lý thuyết thì int * và float * trên cùng một nền tảng có thể có kích thước khác nhau mà không vi phạm bất kỳ quy tắc nào .

Có một yêu cầu là char * và void * có cùng yêu cầu biểu diễn và căn chỉnh, và có nhiều yêu cầu tương tự khác cho các tập hợp con khác nhau của các loại con trỏ nhưng không có gì bao gồm mọi thứ.

Trong thực tế, bạn không thể chạy vào bất kỳ triển khai nào sử dụng các con trỏ có kích thước khác nhau trừ khi bạn đi vào một số địa điểm khá mơ hồ.

3

Có. Nó không phổ biến, nhưng điều này chắc chắn sẽ xảy ra trên các hệ thống không phải là địa chỉ byte. Ví dụ. một hệ thống 16 bit với 64 Kword = 128KB bộ nhớ. Trên các hệ thống như vậy, bạn vẫn có thể có 16 bit int con trỏ. Nhưng một con trỏ char đến một char 8 bit sẽ cần thêm một chút để chỉ ra highbyte/lowbyte trong từ, và do đó bạn sẽ có 17/32 bit char con trỏ.

Điều này nghe có vẻ kỳ lạ, nhưng nhiều DSP dành 99.x% thời gian thực hiện mã số chuyên biệt. Một DSP âm thanh có thể đơn giản hơn một chút nếu tất cả nó phải đối phó với dữ liệu 16 bit, để lại các phép toán 8 bit không thường xuyên được trình biên dịch mô phỏng.

0

Có các nền tảng trong đó các con trỏ hàm có kích thước khác với các con trỏ khác.

Tôi chưa bao giờ thấy nhiều biến thể hơn thế này. Tất cả các con trỏ khác phải có kích thước tối đa (void *) vì tiêu chuẩn yêu cầu chúng có thể bị bỏ trống * mà không làm mất thông tin.

1

Tôi có thể giả định rằng các con trỏ của các loại khác nhau có cùng kích thước (trên một vòm của khóa học) không?

Đối với nền tảng có kích thước con trỏ phẳng (== tất cả phổ biến/nền tảng hiện đại), kích thước con trỏ sẽ giống nhau.

Đối với các nền tảng có mô hình bộ nhớ phân đoạn, để có hiệu quả, thường có các loại con trỏ cụ thể theo nền tảng có kích thước khác nhau. (Ví dụ: far con trỏ trong DOS, vì CPU 8086 sử dụng mô hình bộ nhớ phân đoạn.) Nhưng đây là nền tảng cụ thể và không chuẩn.

Bạn có thể nên nhớ rằng trong kích thước C++ của con trỏ bình thường có thể khác với kích thước của con trỏ đến phương thức ảo. Các con trỏ tới các phương thức ảo phải bảo toàn thêm một chút thông tin để không hoạt động đúng với tính đa hình. Điều này có lẽ chỉ là ngoại lệ mà tôi biết, vẫn còn có liên quan (vì tôi nghi ngờ rằng mô hình bộ nhớ phân đoạn sẽ bao giờ làm cho nó trở lại).

3

Tôi sẽ viết một câu trả lời cho biết rằng C99 có các yêu cầu chuyển đổi con trỏ khác nhau mà ít nhiều đảm bảo rằng con trỏ đến dữ liệu phải có cùng kích thước. Tuy nhiên, khi đọc chúng một cách cẩn thận, tôi nhận ra rằng C99 được thiết kế đặc biệt để cho phép các con trỏ có kích thước khác nhau cho các loại khác nhau.

Ví dụ trên một kiến ​​trúc trong đó các số nguyên là 4 byte và phải được 4 byte căn chỉnh một con trỏ int có thể là hai bit nhỏ hơn một con trỏ char hoặc void. Với điều kiện dàn diễn viên thực sự chuyển đổi theo cả hai hướng, bạn sẽ ổn với C99. Nó khéo léo nói rằng kết quả của việc đúc một con trỏ char đến một con trỏ int không chính xác là không xác định.

Xem C99 standard. Mục 6.3.2.3

+0

Chính xác đúng - tiêu chuẩn đã hết hạn để cho phép điều này. – caf

+0

Bạn có thể cung cấp liên kết đến nơi bạn đọc chính xác địa chỉ đó không? – Nils

+0

thx :) (Mục 6.3.2.3 bắt đầu từ trang 47 cho những người quan tâm) – Nils

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