何时使用无符号字符指针
When to use unsigned char pointer
unsigned char
指针的用途是什么?我在很多地方看到指针是类型转换为指向unsigned 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
}
您实际上正在寻找指针算术:
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
等于' '
(终止字符)。如果您的字符缓冲区总是以' '
结尾,那么您不需要知道它的长度,因为终止字符正好指定数据的末尾。
请注意,在这两种情况下,最好使用一些对象来隐藏数据的内部表示,并为您负责内存管理(请参阅RAII习惯用法)。因此,最好使用std::vector<unsigned char>
(用于二进制数据)或std::string
(用于字符串)。
在C中,unsigned char
是唯一保证没有陷阱值的类型,它保证复制将产生精确的逐位图像。(C++也将这种保证扩展到了char
。)因此,它传统上被用于"原始内存"(例如,memcpy
的语义是根据unsigned char
定义的)。
此外,当要使用逐位运算(&
、|
、>>
等)时,通常使用无符号积分类型。unsigned char
是最小的无符号积分类型,可以在操作使用逐位运算的小值数组时使用。偶尔,它也会被使用,因为在溢出的情况下需要模行为,尽管这种情况在较大的类型中更常见(例如,在计算哈希值时)。这两个原因通常都适用于无符号类型;CCD_ 29通常仅在需要减少内存使用时用于它们。
unsinged char
类型通常用作二进制数据的单个byte
的表示。因此,和数组经常被用作二进制数据缓冲区,其中每个元素都是一个单字节。
unsigned char*
构造将是指向二进制数据缓冲区(或其第一个元素)的指针。
对于unsigned char
的大小,无论它是否固定为8位,我都不能100%确定c++
标准到底说了什么通常是。我会设法找到并发布它。
看到您的代码后
当您使用类似void* input
的东西作为函数的参数时,您会故意去掉输入原始类型的信息。这是一个非常强烈的建议,即将以非常一般的方式处理输入。即作为任意的字节串。另一方面,int* input
建议将其视为有符号整数的"字符串"。
void*
主要用于对输入进行编码或出于任何原因对bit
/byte
进行处理的情况,因为您无法对其内容得出结论。
然后,在您的函数中,您似乎希望将输入视为一个字节字符串但是要对对象进行操作,例如执行operator=
(赋值),编译器需要知道该做什么。由于将输入声明为void*
赋值(如*input = something
),因此*input
属于void
类型,因此没有任何意义。为了使编译器将input
元素视为"最小的原始内存块",您将其转换为适当的类型unsigned int
。
cout
可能由于错误或意外的类型转换而无法工作。char*
被认为是一个以null结尾的字符串,在代码中很容易混淆singed
和unsigned
版本。如果将unsinged char*
作为char*
传递给ostream::operator<<
,则会将byte
输入视为普通ASCII字符,其中0
是字符串的末尾,而不是0
的整数值。当您想要打印内存的内容时,最好显式地投射指针。
还要注意,要打印缓冲区的内存内容,您需要使用循环,因为其他方面的打印功能不知道何时停止。
当您想要逐字节访问数据时,无符号字符指针非常有用。例如,将数据从一个区域复制到另一个区域的功能可能需要以下内容:
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++中,零字符标记字符串的结束。
- 指向指向字符数组的指针数组的指针
- 将字符指针十六进制转换为字符串并保存在文本文件C++中
- 将字符缓冲区强制转换为函数指针
- 在函数中返回无符号字符数组,但不返回指针
- 将字符逐个分配给指针?
- 如何返回实际值(在我的例子中是无符号字符数组)而不是来自 C++ 函数的指针?
- 如何循环访问 cpp 中的函数返回的字符指针数组
- 将字符数组复制到 QByte 数组中,而无需传递指针
- C++:使用没有位移位的指针将无符号字符转换为无符号 int
- C++指针数组到字符数组中的特定位置
- 如何从链表指针字符中查找字符
- 获取字符数组地址,然后转换为指针字符
- 在指针字符 c++ 中分配字符数组的值
- C 指针字符
- 将向量传递<char>到指针字符*
- 如何修复未对齐的指针(字符**)
- 如何打印指针字符数组
- 指针 *字符和 &字符
- C++指针字符
- C/ c++:从指针字符一维数组中访问单个字符