10

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
}
4

4 回答 4

10

您实际上正在寻找指针算术

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有效值且仍然是数据的一部分的二进制数据。在使用“naked”unsigned char*时,您可能必须保持缓冲区的长度。

char通常用于保存表示字符串的字符,0等于'\0'(终止字符)。如果您的字符缓冲区始终以 终止'\0',则您不需要知道它的长度,因为终止字符准确地指定了数据的结尾。

请注意,在这两种情况下,最好使用一些隐藏数据内部表示并为您处理内存管理的对象(请参阅RAII idiom)。所以最好使用std::vector<unsigned char>(二进制数据)或std::string(字符串)。

于 2013-02-08T10:04:59.440 回答
8

在 C 中,unsigned char是唯一保证没有陷印值的类型,并且保证复制将产生精确的按位图像。(C++ 也将此保证扩展到char。)出于这个原因,它传统上用于“原始内存”(例如 的语义是memcpy根据 定义的unsigned char)。

此外,当要使用按位运算( 、 等)时,通常会使用无符号&整数类型 |。是最小的无符号整数类型,可以在处理使用按位运算的小值数组时使用。有时,它也被使用,因为在溢出的情况下需要模行为,尽管这对于较大的类型更常见(例如,在计算哈希值时)。这两个原因通常都适用于无符号类型。通常仅在需要减少内存使用时才用于它们。>>unsigned charunsigned char

于 2013-02-08T10:06:25.760 回答
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*被认为是一个空终止的字符串,很容易在代码中混淆singedunsigned版本化。如果您将unsinged char*ostream::operator<<作为 a传递,char*它会将byte输入视为普通的 ASCII 字符,其中0意味着是字符串的结尾而不是0. 当您想打印内存内容时,最好显式地转换指针。

另请注意,要打印缓冲区的内存内容,您需要使用循环,否则打印函数将不知道何时停止。

于 2013-02-08T10:05:39.817 回答
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++ 中它标志着一串字符的结尾。

于 2013-02-08T10:06:40.240 回答