unsigned char
指针有什么用?我在很多地方都看到过,指针被指定为unsinged char
的指针。为什么我们这样做?
我们收到指向int
的指针,然后输入转换为unsigned char*
。但是如果我们尝试使用cout在该数组中打印元素,它就不会打印任何内容。为什么?我不明白。我是c ++的新手。
编辑以下示例代码
int Stash::add(void* element)
{
if(next >= quantity)
// Enough space left?
inflate(increment);
// Copy element into storage, starting at next empty space:
int startBytes = next * size;
unsigned char* e = (unsigned char*)element;
for(int i = 0; i < size; i++)
storage[startBytes + i] = e[i];
next++;
return(next - 1); // Index number
}
答案 0 :(得分:7)
在C中,unsigned char
是唯一保证没有陷印值的类型,它保证复制将产生精确的按位图像。 (C ++也将此保证扩展到char
。)因此,它传统上用于“原始内存”(例如memcpy
的语义是根据unsigned char
定义的)。
此外,当使用按位运算(&
,|
,>>
等)时,通常使用无符号整数类型。 unsigned char
是最小的无符号整数类型,可以在操作使用按位运算的小值数组时使用。偶尔也会使用它,因为在溢出的情况下需要模数行为,尽管对于较大类型(例如在计算散列值时)这种情况更常见。这两个原因通常都适用于无符号类型;当需要减少内存使用时,unsigned char
通常只会用于它们。
答案 1 :(得分:6)
您实际上在寻找pointer arithmetic:
unsigned char* bytes = (unsigned char*)ptr;
for(int i = 0; i < size; i++)
// work with bytes[i]
在此示例中,bytes[i]
等于*(bytes + i)
,并用于访问地址上的内存:bytes + (i* sizeof(*bytes))
。换句话说:如果您有int* intPtr
但尝试访问intPtr[1]
,则实际上是访问以字节存储的整数:4到7:
0 1 2 3
4 5 6 7 <--
指针指向的类型大小会影响它递增/递减后指向的位置。因此,如果要逐字节地迭代数据,则需要指向大小为1字节的类型的指针(这就是为什么unsigned char*
)。
unsigned char
通常用于保存二进制数据,其中0
是有效值且仍然是数据的一部分。在使用“裸”unsigned char*
时,您可能需要保持缓冲区的长度。
char
通常用于保存表示字符串的字符,0
等于'\0'
(终止字符)。如果您的字符缓冲区始终以'\0'
终止,则您不需要知道它的长度,因为终止字符会准确指定数据的结尾。
请注意,在这两种情况下,最好使用一些隐藏数据内部表示的对象,并为您处理内存管理(请参阅RAII idiom)。因此,最好使用std::vector<unsigned char>
(对于二进制数据)或std::string
(对于字符串)。
答案 2 :(得分:2)
unsinged char
类型通常用作单个byte
二进制数据的表示。因此,数组通常用作二进制数据缓冲区,其中每个元素都是单字节。
unsigned char*
构造将是指向二进制数据缓冲区(或其第一个元素)的指针。
我不是100%确定c++
标准对unsigned char
的大小的准确说明是什么,是否固定为8位。 通常。我会尝试找到并发布它。
看到您的代码后
当您使用void* input
之类的函数作为函数的参数时,您会故意删除有关输入原始类型的信息。这是一个非常强烈的建议,即输入将以非常一般的方式处理。即作为任意字节串。另一方面,int* input
表明它将被视为烧结整数的“字符串”。
void*
主要用于输入被编码或由于任何原因而被视为bit
/ byte
明智的情况,因为您无法得出有关其内容的结论。
然后在您的函数中,您似乎希望将输入视为字节串。 但对对象进行操作,例如执行operator=
(赋值)编译器需要知道该怎么做。由于您将输入声明为void*
,因此*input = something
之类的分配没有任何意义,因为*input
属于void
类型。要使编译器将input
元素视为“最小的原始内存块”,请将其转换为适当的类型unsigned int
。
由于错误或无意的类型转换,cout
可能无法正常工作。 char*
被视为以空字符结尾的字符串,很容易在代码中混淆singed
和unsigned
版本。如果您将unsinged char*
作为ostream::operator<<
传递给char*
,它会将byte
输入视为普通的ASCII字符,其中0
意味着结束字符串不是0
的整数值。当你想打印内存的内容时,最好显式地转换指针。
另请注意,要打印缓冲区的内存内容,您需要使用循环,因为其他方面打印功能不知道何时停止。
答案 3 :(得分:0)
当您想要逐字节访问数据时,无符号的char指针非常有用。例如,将数据从一个区域复制到另一个区域的功能可能需要这样:
void memcpy (unsigned char* dest, unsigned char* source, unsigned count)
{
for (unsigned i = 0; i < count; i++)
dest[i] = source[i];
}
它还与字节是存储器的最小可寻址单元这一事实有关。如果要从内存中读取小于一个字节的任何内容,则需要获取包含该信息的字节,然后使用位操作选择信息。
您可以使用int
指针复制上述函数中的数据,但这会复制4个字节的块,这在某些情况下可能不是正确的行为。
当您尝试使用cout
时屏幕上没有显示任何内容,最可能的解释是数据以零字符开头,在C ++中标记字符串的结尾。