Подтвердить что ты не робот

Быстрое чтение памяти: "подписанный char *" vs "unsigned char *"

Часто нужно читать из памяти по одному байту за раз, как в этой наивной реализации 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].

4b9b3361

Ответ 1

Вы должны использовать unsigned char. В стандарте C99 говорится, что unsigned char является единственным типом, который гарантированно будет плотным (без битов заполнения), а также определяет, что вы можете скопировать любой объект (за исключением битовых полей) точно, скопировав его в массив unsigned char, который является объектом представление в байтах.

Разумная интерпретация этого для меня заключается в том, что если вы используете указатель для доступа к объекту в виде байтов, вы должны использовать unsigned char.

Ссылка: http://blackshell.com/~msmud/cstd.html#6.2.6.1 (из C1x draft C99)

Ответ 2

Это одна точка, где С++ отличается от C. Вообще говоря, только C гарантирует, что доступ к необработанной памяти работает для unsigned char; char может быть подписанным, а на 1 дополняющей или подписанной машине величин a -0 может быть автоматически преобразовано в +0, изменив битовый шаблон. Для по какой-то причине (неизвестно мне) комитет С++ расширяет гарантии поддерживая прозрачную копию (без изменения битовых паттернов) до char, так как а также unsigned char; на 1 дополняющую или подписанную величину машины, у разработчиков нет выбора, кроме как сделать простой char без знака, чтобы избежать таких побочных эффектов. (И, конечно, большинство программисты сегодня не интересуются такими машинами в любом случае.)

В любом случае, конечный результат заключается в том, что более старые программисты, которые приходят из C (и, возможно, фактически работал над 1 дополнением или знаковая машина) автоматически будет использовать unsigned char. Это также частое соглашение о резервировании plain char для символьных данных однозначно, при signed char для очень малых интегральных значений и unsigned char для необработанной памяти или когда используется бит-манипуляция. Такое правило позволяет читателю различать различные виды использования (при условии, что это соблюдается религиозно).

Ответ 3

В вашем примере кода это не имеет значения. Но если вы хотите отобразить/распечатать значение байта, чем оно (поскольку старший бит интерпретируется по-разному), а unsigned char кажется более подходящим

Ответ 4

Это зависит от того, что вы хотите сохранить в char. Подписанный char дает диапазон от -127 до 127, тогда как unsigned char находится в диапазоне от 0 до 255.

Для арифметики указателя это не имеет значения.

Ответ 5

#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 оба имеют одинаковое значение, поэтому в данном случае это не имеет значения

Изменить

, если вы прочтете что-либо в качестве подписанного char, все же в этом случае большинство бит высокого уровня также будет скопирован, поэтому не имеет значения