2009-12-04 40 views
9

Tôi đang ở giữa dự án C này mà tôi muốn làm cho bộ nhớ rất hiệu quả. Trong một số trường hợp, tôi đang sử dụng void * s của một cấu trúc mảng động mà tôi đã viết để giữ bit. Tôi muốn sử dụng tất cả 64 (trong trường hợp này) bit.Thay đổi bit trên một con trỏ C?

Tôi sớm nhận ra rằng bạn không thể thực sự thực hiện bất kỳ thao tác bit nào trên con trỏ. Vì vậy, giải pháp của tôi là như sau:

void *p; 
((unsigned long)p) << 4; 
((unsigned long)p) & 3; 

Việc này được thực hiện, nhưng chỉ vì trên máy tính của tôi, thời gian và con trỏ có kích thước bằng nhau. Đây có phải là trường hợp trong tất cả (hoặc hầu hết) kiến ​​trúc?

Và câu hỏi thực sự của tôi: Có cách nào đúng hơn để thực hiện thao tác bit trên con trỏ không? Tôi đã nghĩ rằng phương pháp này là hơi phổ biến ở C (đóng gói bit thành một void *), nhưng tôi có thể bị nhầm lẫn ...

+0

Tôi sẽ sử dụng uint64_t thay vì từ stdint.h – sambowry

+2

uint64_t sẽ quá lớn nếu nền tảng của bạn có con trỏ ít hơn 64 bit. Sử dụng intptr_t và uintptr_t từ cùng một tiêu đề. – tgamblin

+0

@sambowry - Có vẻ như bạn cần phải đi qua 'stdint.h' một chút gần hơn. –

Trả lời

15

Nếu trình biên dịch của bạn hỗ trợ nó, <stdint.h> tiêu đề C99 của cung cấp các loại intptr_tuintptr_t rằng nên đủ lớn để giữ con trỏ trên hệ thống của bạn, nhưng là số nguyên, vì vậy bạn có thể thực hiện thao tác bit. Nó thực sự không thể di chuyển nhiều hơn thế, nếu đó là những gì bạn đang tìm kiếm.

+0

Dù sao, bạn có thể không cần một giải pháp hoàn toàn di động. Bất kỳ bit-twiddling mà cố gắng để lưu trữ cờ trong bit thấp hơn của con trỏ là nhất thiết nền tảng cụ thể, vì nó dựa trên các giả định về sự liên kết đối tượng. Vì vậy, người hỏi có thể sẽ phải làm một số công việc (hoặc ít nhất là nghiên cứu) khi chuyển sang một nền tảng mới anyway. –

+0

@Steve - Nếu anh ta làm bit twiddling trên một con trỏ, tôi chắc chắn hy vọng anh ta không dereferencing nó sau này. Điều đó nghe có vẻ giống như một cơn ác mộng di động.Nếu anh ta làm điều đó, tôi nghi ngờ anh ta sẽ hỏi về tính di động của các hoạt động của anh ấy. –

+1

Bạn có thể giải thích sự khác biệt giữa 'intptr_t' và' uintptr_t' không? – DRz

2

Khai báo một liên kết của con trỏ và một bitfield.

+1

Bạn vẫn cần phải biết làm thế nào lớn để làm cho bitfield, do đó, lĩnh vực khác của bạn sẽ cần phải là một intptr_t. Tôi không chắc liệu điều này hay việc đúc sẽ dễ đọc hơn. – tgamblin

+1

Bạn làm cho bitfield lớn như nó cần cho các mục đích khác của bạn. Trình biên dịch sau đó sẽ đảm bảo rằng cấu trúc là đủ lớn sao cho lớn hơn ra khỏi con trỏ và bitfield phù hợp với nó. Tình trạng này là chính xác những gì các đoàn thể là cho. –

7

Nếu bạn cần thực hiện loại thao tác này trên con trỏ, bạn có thể truyền chúng đến intptr_tuintptr_t, cả hai đều có thể được tìm thấy trong stdint.h. Đây là những đảm bảo được định nghĩa là loại số nguyên nền tảng cụ thể với đủ bit để giữ con trỏ.

Ngoài ra còn có ptrdiff_t trong đó, nếu bạn cần một cái gì đó để giữ sự khác biệt giữa hai con trỏ.

+4

Và nếu trình biên dịch của bạn không hỗ trợ stdint.h (* ho * Microsoft * cough *), câu trả lời và nhận xét SO sau có liên kết đến một số bạn có thể quyết định sử dụng: http://stackoverflow.com/questions/126279/ c99-stdint-h-header-và-ms-visual-studio/126285 # 126285 –

3

Tôi nghĩ bạn đang cố giải quyết vấn đề sai. Vấn đề thực sự là ngay tại đây:

Tôi đang sử dụng void * s của cấu trúc mảng động Tôi đã viết để giữ bit.

Không sử dụng con trỏ void để giữ bit. Sử dụng con trỏ void để giữ con trỏ. Sử dụng số nguyên không dấu để giữ bit.

+0

Tôi không chắc chắn rằng tôi sẽ đồng ý rằng thực tế của nó để viết lại toàn bộ cấu trúc dữ liệu và tất cả các hàm liên quan của nó để có thể lưu trữ các giá trị con trỏ không. Sau đó, một lần nữa, có lẽ nếu tôi đã viết cấu trúc dữ liệu của mình chính xác hơn, tôi sẽ không gặp phải vấn đề này. – MADgood

+0

Vâng, bạn có thể sử dụng Excel làm cơ sở dữ liệu nếu bạn muốn tránh việc học thêm về cơ sở dữ liệu, nhưng liệu đó có phải là một ý tưởng hay về lâu dài không? Hãy lưu ý rằng chuyển đổi con trỏ đến int và ngược lại được thực hiện hoàn toàn được xác định và nếu bạn không cẩn thận với việc xử lý, bạn có thể kết thúc bằng hành vi không xác định. Cấu trúc của bạn được dự định để lưu trữ con trỏ. Tại sao không viết một cơ sở dữ liệu BitStore chuyên lưu trữ bit, với tất cả các bit twiddling đã có bên trong, vì vậy bạn không phải chăm sóc cho nó trên mỗi cuộc gọi? – Secure

+0

-1 để rao giảng cho OP. Có vẻ như anh ta biết mình muốn gì. –

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