通常需要一次一个字节地从内存中读取,就像在这个天真的memcpy()
实现中一样:
void *memcpy(void *dest, const void *src, size_t n)
{
char *from = (char *)src;
char *to = (char *)dest;
while(n--) *to++ = *from++;
return dest;
}
但是,我有时会看到人们明确使用unsigned char *
而不只是char *
。
当然,char
和unsigned char
可能不相等。但是,当按字节顺序读/写内存时,我是否使用char *
,signed char *
或unsigned char *
会有所不同吗?
更新:实际上,我完全清楚c=200
可能会有不同的值,具体取决于c
的类型。我在这里问的是,为什么人们在阅读内存时有时会使用unsigned char *
而不是char *
,例如为了在uint32_t
中存储char[4]
。
答案 0 :(得分:21)
您应该使用unsigned char
。 C99标准说unsigned char
是唯一保证密集的类型(没有填充位),并且还定义了您可以通过将任何对象(位域除外)复制到unsigned char
数组中来精确复制它,这是对象表示,以字节为单位。
对我来说明智的解释是,如果你使用指针来访问对象作为字节,你应该使用unsigned char
。
参考:http://blackshell.com/~msmud/cstd.html#6.2.6.1(来自 C1x草案 C99)
答案 1 :(得分:12)
这是C ++与C不同的一点。一般来说,只有C
保证原始内存访问适用于unsigned char
; char
可以
签名,并在1的补码或签名幅度的机器上,--0
可能会自动转换为+0,更改位模式。对于
某些原因(我不知道),C ++委员会扩展了保证
支持透明副本(位模式没有变化)到char
,如
unsigned char
;在1的补码或有符号的幅度上
机器,实现者别无选择,只能做出简单char
无符号,以避免这种副作用。 (当然,大多数人
今天的程序员无论如何都不关心这样的机器。)
无论如何,最终的结果是来自C的老程序员
背景(也许实际上是在1的补码或者
签名量级机器)将自动使用unsigned char
。它的
也是为字符数据保留普通char
的常用惯例
唯一的,signed char
表示非常小的积分值,和
unsigned char
表示原始内存,或意图进行位操作。
这样的规则允许读者区分不同的用途
(如果遵循宗教信仰)。
答案 2 :(得分:2)
在您的代码示例中,它没有任何区别。但是如果你想显示/打印字节的值而不是(因为最高位的解释不同),unsigned char
似乎更合适
答案 3 :(得分:0)
这取决于你想要存储在char中的内容。 带符号的char给出的范围是-127到127,而unsigned char的范围是0到255。
对于指针算术而言无关紧要。
答案 4 :(得分:0)
#include<stdio.h>
#include<string.h>
int main()
{
unsigned char a[4]={254,254,254,'\0'};
unsigned char b[4];
char c[4];
memset(b,0,4);
memset(c,0,4);
memcpy(b,a,4);
memcpy(c,a,4);
int i;
for(i=0;i<4;i++)
{
printf("\noriginal is %d",a[i]);
printf("\nchar %d is %d",i,c[i]);
printf("\nunsigned char %d is %d \n\n",i,b[i]);
}
}
输出
original is 254
char 0 is -2
unsigned char 0 is 254
original is 254
char 1 is -2
unsigned char 1 is 254
original is 254
char 2 is -2
unsigned char 2 is 254
original is 0
char 3 is 0
unsigned char 3 is 0
所以这里char和unsign都有相同的值,所以在这种情况下无关紧要
修改
如果您在某种情况下阅读任何已签名的字符,那么大多数高级位也会复制,因此无关紧要