2011-02-06 66 views
6

Tôi đang sử dụng mã này để di chuyển con trỏ bằng 1 byte bây giờ, nhưng tôi cảm thấy một cái gì đó không rõ ràng ..Cách chính xác để thêm 1 byte vào một con trỏ trong C/C++ là gì?

int* a = (int*)malloc(sizeof(int)); 
void* b = ((char*)a)+1; 

char là 1 byte, nhưng không được định nghĩa cho mục đích hoạt động byte. Tôi tin rằng có một cách khác để thực hiện thao tác này byte. chính xác cách nào để hoạt động byte?

PS. Tôi đã sửa đổi mã mẫu để hợp lệ. Nó bây giờ được biên dịch là C++ với Clang.

+0

Bạn đang sử dụng C hoặc C++? Mã bạn đã hiển thị không hợp lệ cho cả hai. Và bạn có ý nghĩa gì bởi "' char' không được định nghĩa cho hoạt động byte "? –

+5

Không có cách nào đúng để thực hiện việc này; những gì bạn đang làm gây ra hành vi không xác định. –

+0

Tôi không biết tại sao điều này lại bị giảm giá. Ngay cả khi mục đích có vẻ tanh, câu hỏi là hợp pháp. –

Trả lời

4

Tôi nghĩ rằng bạn đang nhầm lẫn:

char là 1 byte, nhưng không được định nghĩa cho mục đích hoạt động byte. Tôi tin rằng có một cách khác để thực hiện thao tác này byte. chính xác cách nào để hoạt động byte?

Chính xác thì bạn đang mong chờ gì byte có nghĩa là, nếu không phải điều chính xác tương tự thì char có nghĩa là gì?

Trong C và trong C++, ký tự byte. Theo định nghĩa. không trường hợp nào là byte nhất thiết phải là octet. Một byte chứa ít nhất 8 bit. Có không đảm bảo rằng một nền tảng nhất định thậm chí làm cho nó có thể để tham chiếu một đoạn bộ nhớ là chính xác 8 bit.

+0

Wow! Cảm ơn! Bạn đã giúp tôi rất nhiều! Đây là những gì tôi muốn! – Eonil

1
((char*&)a)++; 

Hoặc:

a = (int*)((char*)a+1); 

Tôi hy vọng bạn biết chính xác những gì bạn đang làm. Đối với một điều, bạn đang kết thúc với - theo định nghĩa - unaligned int pointer. Tùy thuộc vào kiến ​​trúc và hệ điều hành, điều này có thể gây rắc rối.

+4

Không chỉ là một con trỏ không có dấu, nhưng nó không hợp lệ vì nó mở rộng ra ngoài giới hạn của bộ đệm được cấp phát. –

4

Trong C99, bạn có tiêu đề stdint.h, có chứa các loại int8_tuint8_t, được đảm bảo là 8 bit (và thường chỉ là typedef cho char). Ngoài điều này, không có hỗ trợ mức ngôn ngữ thực cho các byte trong C hoặc C++, trên thực tế, tiêu chuẩn này không được dùng để nói rằng sizeof ví dụ là theo đơn vị char (và không phải byte). Ngoài ra còn có macro CHAR_BIT cho bạn biết số bit trong một byte, trên một số nền tảng char là 9 bit chẳng hạn. Tất nhiên tôi giả sử bởi byte bạn có nghĩa là octet.

+0

Cảm ơn. Có vẻ như khái niệm 'byte' hoàn toàn trừu tượng trong C/C++. Đúng? Và nếu vậy, 'char' phải là đơn vị tối thiểu của kiểu dữ liệu. Là nó? – Eonil

+1

Vì vậy, char là đơn vị tối thiểu của kiểu dữ liệu, ngoại trừ các trường bit. Tuy nhiên, vì bạn không thể đặt tên kiểu trường bit (và do đó không thể có con trỏ đến nó, hoặc lấy địa chỉ của nó) hoặc thực hiện số học con trỏ trong đơn vị nhỏ hơn char, vì mục đích của con trỏ, char là tối thiểu, vâng. –

+1

Đó là 'CHAR_BIT', không phải' CHAR_BITS'. – caf

2

((char*)a)++

Đây là một trong những phần mở rộng của Microsoft ác. Biểu thức truyền con trỏ là một giá trị, nhưng theo các quy tắc ngôn ngữ C++, toán tử gia tăng chỉ hoạt động trên các giá trị. g ++ từ chối biên dịch.

+0

Cảm ơn bạn đã sửa. Tôi đã sửa đổi câu hỏi của mình :) – Eonil

2

Bạn không nên làm điều này. Nhiều kiến ​​trúc có yêu cầu căn chỉnh dữ liệu. Ví dụ, dereferencing một con trỏ không liên kết với một ranh giới từ trên một máy SPARC, sẽ sụp đổ chương trình với một lỗi Bus (SIGBUS).


Cách di động để chia int của bạn vào byte là bằng cách sử dụng các hoạt động Bitwise (giả sử 8-bit byte):

uint8_t b3 = 0x12, b2 = 0x34, b1 = 0x56, b0 = 0x78; 
uint32_t a; 

a = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; 

printf("%08X\r\n", a); 

a = 0x89ABCDEF; 

b3 = (a >> 24) & 0xFF; 
b2 = (a >> 16) & 0xFF; 
b1 = (a >> 8) & 0xFF; 
b0 = a & 0xFF; 

printf("%02X%02X%02X%02X\r\n", b3, b2, b1, b0); 

Cùng thể phi portably đạt được với type punning các mẹo thông qua union s, chẳng hạn như:

typedef union { 
    uint32_t val; 
    uint8_t bytes[4]; 
} DWORD_A; 

typedef union { 
    uint32_t val; 
    struct { 
     unsigned b0:8; 
     unsigned b1:8; 
     unsigned b2:8; 
     unsigned b3:8; 
    }; 
} DWORD_B; 

Tuy nhiên, kỹ thuật này dẫn đến hành vi thực hiện xác định và do đó là không được khuyến khích :

  • trật tự Byte phụ thuộc vào endianness hệ thống máy chủ của.
  • Việc đóng gói các trường bit không thể di chuyển được.
  • Đã thêm mức độ phức tạp/chi phí do mã được tạo bởi trình biên dịch để ngăn truy cập không được điều chỉnh.
  • Các vấn đề liên quan đến các triển khai không ngăn cản chúng.
+0

Cảm ơn. Tôi không biết về sự liên kết chi tiết. Nếu vậy, nó có thể là không thể làm cho mã thao tác byte di động. Có vẻ như yêu cầu bất kỳ loại trừu tượng nào. – Eonil

+0

Nếu bạn có một đoạn dữ liệu bạn cần truy cập byte-by-byte, bạn có thể khai báo nó dưới dạng mảng 'char' ở vị trí đầu tiên. Ngoài ra, phương pháp dịch chuyển bit mà tôi đã giới thiệu, là di động. Xem http://c-faq.com/strangeprob/ptralign.html để biết thêm thông tin. – mizo

0

plz, sử dụng void *

int g = 10; 
int *a = &g; 
printf("a : %p\n",a); 
printf("a : %p\n", ++a); 
printf("a : %p\n", (void*)((char*)a+1)); 

a: 0xbfae35dc a: 0xbfae35e0 a: 0xbfae35e1

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