Как memset инициализирует массив целых чисел на -1?

manpage говорит о memset:

#include <string.h>
void *memset(void *s, int c, size_t n)

Функция memset() заполняет первую n байты области памяти, на которую указывает s, с константным байтом c.

Очевидно, что memset не может использоваться для инициализации массива int, как показано ниже:

int a[10];
memset(a, 1, sizeof(a));  

это потому, что int представляется 4 байтами (скажем), и невозможно получить желаемое значение для целых чисел в массиве a.
Но я часто вижу, что программисты используют memset для установки элементов массива int либо 0, либо -1.

int a[10];
int b[10];
memset(a, 0, sizeof(a));  
memset(b, -1, sizeof(b));  

В соответствии с моим пониманием инициализация с помощью integer 0 является ОК, потому что 0 может быть представлена ​​в 1 байт (может быть, я ошибаюсь в этом контексте). Но как можно инициализировать b с помощью -1 (значение 4 байта)?

Ответ 1

Как ни странно, причина, по которой это работает с -1, точно такая же, как причина, что это работает с нулями: в двухкомпонентное двоичное представление, -1 имеет 1 во всех своих битах, независимо от размера целого числа, поэтому заполнение области байтами, заполненными всеми 1, создает область -1, подписанную int s, long s и short на двух дополнительных аппаратных средствах.

На аппаратном обеспечении, отличном от двух дополнений, результат будет другим. Целочисленная константа -1 была бы преобразована в unsigned char для всех, поскольку стандарт специфичен для того, как должно выполняться преобразование. Однако область байтов со всеми их битами, установленными в 1, будет интерпретироваться как интегральные значения в соответствии с правилами платформы. Например, на аппарате с знаками и значениями все элементы вашего массива будут содержать наименьшее отрицательное значение соответствующего типа.

Ответ 2

Когда все биты числа равны 0, его значение также равно 0. Однако, если все биты равны 1 значение равно -1.


Когда мы записываем int a[2], выделяется 4x2 байта памяти, которая содержит случайный мусор bits-

00110000 00100101 11100011 11110010    11110101 10001001 00111000 00010001


Затем мы пишем memset(a, 0, sizeof(a)). Теперь memset() не различает int и char. Работает побайтово. И одно байтовое представление 0 равно 00000000. Итак, мы get-

00000000 00000000 00000000 00000000    00000000 00000000 00000000 00000000

Следовательно, a[0] и a[1] инициализируются с 0.


Теперь давайте посмотрим memset(a, -1, sizeof(a)): один байт для -1 равен 11111111. И мы get-

11111111 11111111 11111111 11111111    11111111 11111111 11111111 11111111

Здесь и a[0] и a[1] будут иметь значение -1.


Однако для memset(a, 1, sizeof(a)): 1 в байте равно 00000001 -

00000001 00000001 00000001 00000001    00000001 00000001 00000001 00000001

Итак, значение будет be- 16843009.