Використання atmset для цілого масиву в c

char str[]="beautiful earth";
memset(str,'*',6);
printf("%s",str);

output:
******ful earth

1) Як наведене вище використанням memset, чи можемо ми ініціалізувати лише кілька цілих значень індексу масиву до 1, як зазначено нижче?

int arr[15];
memset(arr,1,6);
24
@ JoeFrambach Прийнята відповідь на це питання тут не застосовується.
додано Автор Jim Balter, джерело
Ви завжди можете прочитати документацію memset, щоб дізнатись, що вона робить.
додано Автор Jim Balter, джерело
Ви завжди можете прочитати документацію memset, щоб дізнатись, що вона робить.
додано Автор Jim Balter, джерело
можливий дубльований повний масив пам'яті?
додано Автор Joe Frambach, джерело
Ні. memset() зводиться до байтів і дублює його по всьому регіону.
додано Автор Mysticial, джерело
Ні. memset() зводиться до байтів і дублює його по всьому регіону.
додано Автор Mysticial, джерело

17 Відповіді

Ні, ви не можете використовувати такий спосіб memset() . У розділі говориться (наголос мій):

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

Оскільки int , як правило, 4 або 8 байт, це не буде скорочувати його.


Якщо ви ( неправильно !! ) спробуєте це зробити:

int arr[15];
memset(arr, 1, 6*sizeof(int));    //wrong!

то перший 6 int s в масиві буде фактично встановлено 0x01010101 = 16843009.

Єдиний раз, коли коли-небудь дійсно прийнятно писати за "blob" даних з небайтовим типом даних, це memset (thing, 0, sizeof (thing)); до "zero-out" "весь блок/масив. Це працює тому, що NULL, 0x00000000, 0.0, всі повністю нулі.


Рішенням є використання циклу for і встановити його самостійно:

int arr[15];
int i;

for (i=0; i<6; ++i)   //Set the first 6 elements in the array
    arr[i] = 1;       //to the value 1.
34
додано
Нестандартне питання, я думав, що робота з мінструментом на покажчиках, arr - це не покажчик.
додано Автор briankip, джерело
@ MikeWoolf Правильно. Мій коментар був направлений до ОП. Звичайно, він може кодувати все, що завгодно, але якщо він сподівається, що якимсь чином спонукає memset в ініціалізації його масиву, він закінчиться погано.
додано Автор Jonathon Reinhart, джерело
@JimBalter Хоча ви технічно правильні, мені буде цікаво дізнатись про будь-яку платформу, де NULL не відрізняється від нуля.
додано Автор Jonathon Reinhart, джерело
@ user1762571 Не робіть цього. Це неправильно, просто і просто.
додано Автор Jonathon Reinhart, джерело
@briankip Масив розпадається на покажчик тут. & є необов'язковим у цьому випадку; memset (& arr, ...) буде робити те ж саме.
додано Автор Jonathon Reinhart, джерело
додано Автор Jim Balter, джерело
"NULL, 0x00000000, 0.0, всі повністю нулі". - NULL не обов'язково всі (або будь-які) 0 біт.
додано Автор Jim Balter, джерело
@Jonathon, я згоден з неправильною справою, але претензія полягає в тому, що memset веде себе таким чином, що принципово відрізняється від того, що вона повинна робити. Я вказав, що напевно це не так, і описав спосіб дійсно перевірити це.
додано Автор Mike Woolf, джерело
Я був би більш впевнений, що ваша вимога memset зробила це, якщо ви почнете ініціалізувати весь масив на 0 (використовуючи int arr [15] = {0}), а потім виконувати memset (arr, 1, 8); І якщо у вас є масив, повний 0x01010101 після цього, у вас є помилка c runtime :-).
додано Автор Mike Woolf, джерело
У моїй системі розмір int становить 4 байти. Так що я спробував memset (arr, 1,8). Але це ініціалізує весь масив з таким 4 байтівним значенням, замість того, щоб заповнювати лише перші 8 байт за моїм третім аргументом.
додано Автор user1762571, джерело

Коротка відповідь, НІ.

Довгий відповідь, memset встановлює байти і працює для символів, оскільки вони є окремими байтами, але цілих чисел не є.

12
додано
така логічно приваблива відповідь!
додано Автор piyukr, джерело

Коротка відповідь, НІ.

Довгий відповідь, memset встановлює байти і працює для символів, оскільки вони є окремими байтами, але цілих чисел не є.

12
додано
така логічно приваблива відповідь!
додано Автор piyukr, джерело
memset((char *)&tab, 0, sizeof(tab));
5
додано
Це насправді не є відповіддю, оскільки одна справа запитала про те, що arr не tab .
додано Автор Elliott Frisch, джерело

The third argument of memset is byte size. So you should set total byte size of arr[15]

memset(arr, 1, sizeof(arr));

Однак, напевно, ви хочете встановити значення 1 для цілих елементів у arr. Тоді вам краще встановити цикл.

for (i = 0; i < sizeof(arr)/sizeof(arr[0]); i++) {
    arr[i] = 1;
}

Тому що memset() встановлюється 1 в кожному байті. Отже, це не те, що ви очікуєте.

3
додано
@ user1762571 "ініціалізує весь масив з таким 4-байтовим значенням, замість того, щоб заповнювати лише перші 8 байтів відповідно до мого третього аргументу" - ні, це лише налаштування 8 байтів. Ви щось неправильно трактуєте результати або ви копіюєте початкові байти до решти масиву.
додано Автор Jim Balter, джерело
Ви не повинні використовувати постійну величину 8, вам краще використовувати кількість елементів. наприклад n * sizeof (int) .
додано Автор mattn, джерело
При виклику memset (arr, 1, 4) він стає 0x01 0x01 0x01 0x01. Але очікуваним є 0x00 0x00 0x00 0x01 . (Це залежить від архітектури вашого ЦП).
додано Автор mattn, джерело
Як я писав вище, ви не повинні використовувати memset, якщо ви хочете встановити значення 1 для кожного елемента (не встановлюється 1 для кожного байта).
додано Автор mattn, джерело
Але в моїй системі розмір int становить 4 байти. Так що я спробував memset (arr, 1,8). Але це ініціалізує весь масив з таким 4 байтівним значенням, замість того, щоб заповнювати лише перші 8 байт за моїм третім аргументом
додано Автор user1762571, джерело
зрозумів. Дякую. Я спробував memset (arr, 1,2 * sizeof (int)); як ви сказали, але все одно ініціалізує весь масив з таким же значенням.
додано Автор user1762571, джерело

The third argument of memset is byte size. So you should set total byte size of arr[15]

memset(arr, 1, sizeof(arr));

Однак, напевно, ви хочете встановити значення 1 для цілих елементів у arr. Тоді вам краще встановити цикл.

for (i = 0; i < sizeof(arr)/sizeof(arr[0]); i++) {
    arr[i] = 1;
}

Тому що memset() встановлюється 1 в кожному байті. Отже, це не те, що ви очікуєте.

3
додано
@ user1762571 "ініціалізує весь масив з таким 4-байтовим значенням, замість того, щоб заповнювати лише перші 8 байтів відповідно до мого третього аргументу" - ні, це лише налаштування 8 байтів. Ви щось неправильно трактуєте результати або ви копіюєте початкові байти до решти масиву.
додано Автор Jim Balter, джерело
Ви не повинні використовувати постійну величину 8, вам краще використовувати кількість елементів. наприклад n * sizeof (int) .
додано Автор mattn, джерело
При виклику memset (arr, 1, 4) він стає 0x01 0x01 0x01 0x01. Але очікуваним є 0x00 0x00 0x00 0x01 . (Це залежить від архітектури вашого ЦП).
додано Автор mattn, джерело
Як я писав вище, ви не повинні використовувати memset, якщо ви хочете встановити значення 1 для кожного елемента (не встановлюється 1 для кожного байта).
додано Автор mattn, джерело
зрозумів. Дякую. Я спробував memset (arr, 1,2 * sizeof (int)); як ви сказали, але все одно ініціалізує весь масив з таким же значенням.
додано Автор user1762571, джерело
Але в моїй системі розмір int становить 4 байти. Так що я спробував memset (arr, 1,8). Але це ініціалізує весь масив з таким 4 байтівним значенням, замість того, щоб заповнювати лише перші 8 байт за моїм третім аргументом
додано Автор user1762571, джерело

The third argument of memset is byte size. So you should set total byte size of arr[15]

memset(arr, 1, sizeof(arr));

Однак, напевно, ви хочете встановити значення 1 для цілих елементів у arr. Тоді вам краще встановити цикл.

for (i = 0; i < sizeof(arr)/sizeof(arr[0]); i++) {
    arr[i] = 1;
}

Тому що memset() встановлюється 1 в кожному байті. Отже, це не те, що ви очікуєте.

3
додано
@ user1762571 "ініціалізує весь масив з таким 4-байтовим значенням, замість того, щоб заповнювати лише перші 8 байтів відповідно до мого третього аргументу" - ні, це лише налаштування 8 байтів. Ви щось неправильно трактуєте результати або ви копіюєте початкові байти до решти масиву.
додано Автор Jim Balter, джерело
Ви не повинні використовувати постійну величину 8, вам краще використовувати кількість елементів. наприклад n * sizeof (int) .
додано Автор mattn, джерело
Як я писав вище, ви не повинні використовувати memset, якщо ви хочете встановити значення 1 для кожного елемента (не встановлюється 1 для кожного байта).
додано Автор mattn, джерело
При виклику memset (arr, 1, 4) він стає 0x01 0x01 0x01 0x01. Але очікуваним є 0x00 0x00 0x00 0x01 . (Це залежить від архітектури вашого ЦП).
додано Автор mattn, джерело
зрозумів. Дякую. Я спробував memset (arr, 1,2 * sizeof (int)); як ви сказали, але все одно ініціалізує весь масив з таким же значенням.
додано Автор user1762571, джерело
Але в моїй системі розмір int становить 4 байти. Так що я спробував memset (arr, 1,8). Але це ініціалізує весь масив з таким 4 байтівним значенням, замість того, щоб заповнювати лише перші 8 байт за моїм третім аргументом
додано Автор user1762571, джерело

На Linux, OSX та інших UNIX-подібних операційних системах, де wchar_t 32 біти, ви можете використовувати wmemset() замість memset() .

#include
...
int arr[15];
wmemset( arr, 1, 6 );

Зауважте, що wchar_t на MS-Windows становить 16 біт, тому цей трюк може не працювати.

2
додано

На Linux, OSX та інших UNIX-подібних операційних системах, де wchar_t 32 біти, ви можете використовувати wmemset() замість memset() .

#include
...
int arr[15];
wmemset( arr, 1, 6 );

Зауважте, що wchar_t на MS-Windows становить 16 біт, тому цей трюк може не працювати.

2
додано

На Linux, OSX та інших UNIX-подібних операційних системах, де wchar_t 32 біти, ви можете використовувати wmemset() замість memset() .

#include
...
int arr[15];
wmemset( arr, 1, 6 );

Зауважте, що wchar_t на MS-Windows становить 16 біт, тому цей трюк може не працювати.

2
додано

Ні, ви не можете [портативно] використовувати для цієї мети memset , якщо бажане значення не є 0 . memset розглядає область цільової пам'яті як масив байтів, а не масиву int s.

Дуже популярний хак для заповнення області пам'яті з повторюваним шаблоном фактично заснований на memcpy . Він критично спирається на очікування, що memcpy копіює дані в прямому напрямку

int arr[15];

arr[0] = 1;
memcpy(&arr[1], &arr[0], sizeof arr - sizeof *arr);

Це, звичайно, досить потворний хак, оскільки поведінка стандартного memcpy невизначена, коли області пам'яті джерела та призначення перекриваються. Тим не менш, ви можете написати власну версію memcpy , переконавшись, що вона копіює дані у прямому напрямку та використовує вищезазначений спосіб. Але це насправді не варто. Просто використовуйте простий цикл, щоб встановити елементи вашого масиву до потрібного значення.

1
додано

Оскільки ніхто не згадав про це ...

Хоча ви не можете ініціалізувати цілі числа з значенням 1 , використовуючи memset, ви можете ініціалізувати їх значенням -1 і просто змінити свою логіку для роботи з негативним значення замість.

Наприклад, щоб ініціалізувати перші 6 номерів вашого масиву за допомогою -1 , ви б зробили це

memset(arr,-1,6*(sizeof int));

Крім того, якщо вам потрібно лише виконати цю ініціалізацію один раз, ви можете фактично оголосити масив початком з значеннями 1 з часу складання.

int arr[15] = {1,1,1,1,1,1};
0
додано
Ви технічно правильні, але якщо я побачив це в огляді коду, то я, ймовірно, програв би це.
додано Автор Jonathon Reinhart, джерело
Це буде працювати тільки на платформах, що використовують 2-комплект для представлення негативних чисел. Незважаючи на те, що на сьогоднішній день практично кожна платформа - 2-доповнення, це все-таки зламане.
додано Автор AnT, джерело

Оскільки ніхто не згадав про це ...

Хоча ви не можете ініціалізувати цілі числа з значенням 1 , використовуючи memset, ви можете ініціалізувати їх значенням -1 і просто змінити свою логіку для роботи з негативним значення замість.

Наприклад, щоб ініціалізувати перші 6 номерів вашого масиву за допомогою -1 , ви б зробили це

memset(arr,-1,6*(sizeof int));

Крім того, якщо вам потрібно лише виконати цю ініціалізацію один раз, ви можете фактично оголосити масив початком з значеннями 1 з часу складання.

int arr[15] = {1,1,1,1,1,1};
0
додано
Ви технічно правильні, але якщо я побачив це в огляді коду, то я, ймовірно, програв би це.
додано Автор Jonathon Reinhart, джерело
Це буде працювати тільки на платформах, що використовують 2-комплект для представлення негативних чисел. Незважаючи на те, що на сьогоднішній день практично кожна платформа - 2-доповнення, це все-таки зламане.
додано Автор AnT, джерело

Memnes встановлює значення для типів даних, що мають 1 байт, але цілі числа мають 4 байти або більше, тому він не спрацює, і ви отримаєте значення сміття. В основному це використовується, коли ви працюєте з типом символів та рядків.

0
додано

Я намагався виконати таку програму, і з'ясовується, що ви можете ініціалізувати масив за допомогою методу memset() за допомогою -1 і 0

#include
#include

void printArray(int arr[], int len)
{
        int i=0;
    for(i=0; i
0
додано

Я намагався виконати таку програму, і з'ясовується, що ви можете ініціалізувати масив за допомогою методу memset() за допомогою -1 і 0

#include
#include

void printArray(int arr[], int len)
{
        int i=0;
    for(i=0; i
0
додано

Я намагався виконати таку програму, і з'ясовується, що ви можете ініціалізувати масив за допомогою методу memset() за допомогою -1 і 0

#include
#include

void printArray(int arr[], int len)
{
        int i=0;
    for(i=0; i
0
додано