web-dev-qa-db-fra.com

Utiliser memset pour un tableau entier en c

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

output:
******ful earth

1) Comme ci-dessus, utilisation de memset, pouvons-nous n’initialiser que quelques valeurs d’index de tableau entier à 1, comme indiqué ci-dessous?

int arr[15];
memset(arr,1,6);
24
user1762571

Non, vous ne pouvez pas utiliser memset() comme ceci. La page de manuel dit (c’est moi qui souligne):

La fonction memset() remplit la première noctets de la zone mémoire désignée par s avec l'octet constant c.

Etant donné qu'une int est généralement de 4 ou 8 octets, cela ne la coupera pas.


Si vous (incorrectement !! _) essayez de faire ceci:

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

alors les 6 premières ints du tableau seront réellement définies à 0x01010101 = 16843009.

La seule fois où il est vraiment acceptable d'écrire sur un "blob" de données avec un type de données non octet, est memset(thing, 0, sizeof(thing)); pour "mettre à zéro" toute la structure/tableau. Cela fonctionne parce que NULL, 0x00000000, 0.0, sont tous complètement zéros.


La solution consiste à utiliser une boucle for et à la définir vous-même:

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.
36
Jonathon Reinhart

Réponse courte, NON. 

Réponse longue, memset définit des octets et fonctionne pour les caractères car il s'agit d'octets simples, alors que les entiers ne le sont pas. 

12
vidit

Le troisième argument de memset est la taille en octets. Donc, vous devriez définir la taille totale d'octets de arr[15]

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

Cependant, vous devriez probablement vouloir définir la valeur 1 sur des éléments entiers dans arr. Alors vous feriez mieux de mettre dans la boucle.

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

Parce que memset() définissez 1 dans chaque octet. Donc, ce n'est pas votre prévu.

3
mattn

Sous Linux, OSX et autres systèmes d'exploitation similaires à UNIX où wchar_t est 32 bits et vous pouvez utiliser wmemset() au lieu de memset().

#include<wchar.h>
...
int arr[15];
wmemset( arr, 1, 6 );

Notez que wchar_t sur MS-Windows est de 16 bits, donc cette astuce risque de ne pas fonctionner.

3
ceilingcat

Non, vous ne pouvez pas utiliser [portable] memset à cette fin, sauf si la valeur cible souhaitée est 0. memset traite la région de la mémoire cible comme un tableau d'octets et non comme un tableau de ints.

Un hack assez populaire pour remplir une région de mémoire avec un motif répétitif est en fait basé sur memcpy. Il repose essentiellement sur l’espoir que memcpy copie les données dans le sens avant.

int arr[15];

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

Ceci est, bien sûr, un bidon plutôt laid, puisque le comportement de la variable standard memcpy est indéfini lorsque les régions de mémoire source et cible se chevauchent. Vous pouvez cependant écrire votre propre version de memcpy, en vous assurant qu'elle copie les données dans le sens avant, et utilisez-la de la manière indiquée ci-dessus. Mais ça ne vaut pas vraiment la peine. Utilisez simplement un cycle pour définir les éléments de votre tableau à la valeur souhaitée.

1
AnT

Memset définit des valeurs pour les types de données ayant 1 octet mais les entiers ont 4 octets ou plus, cela ne fonctionnera donc pas et vous obtiendrez des valeurs parasites . Il est principalement utilisé lorsque vous utilisez des types char et string.

0
Himanshu Singhvi

Puisque personne n'en a parlé ...

Bien que vous ne puissiez pas initialiser les entiers avec la valeur 1 à l'aide de memset, vous pouvez les initialiser avec la valeur -1 et changez simplement votre logique pour qu'elle utilise des valeurs négatives.

Par exemple, pour initialiser les 6 premiers chiffres de votre tableau avec -1, vous feriez

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

De plus, si vous ne devez effectuer cette initialisation qu'une seule fois, vous pouvez en fait déclarer que le tableau doit commencer par les valeurs 1 à partir de la compilation.

int arr[15] = {1,1,1,1,1,1};
0
i Code 4 Food

Idéalement, vous ne pouvez pas utiliser memset pour définir votre arrary sur 1.
Parce que memset fonctionne sur octet et définit chaque octet sur 1.

memset(hash, 1, cnt);

Donc, une fois lu, la valeur qu'il affichera 16843009 = 0x01010101 = 1000000010000000100000001
Not 0x00000001
Mais si votre requiremnt est uniquement pour bool ou une valeur binaire, alors nous pouvons définir en utilisant la norme C99 pour la bibliothèque C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>        //Use C99 standard for C language which supports bool variables

int main()
{
    int i, cnt = 5;
    bool *hash = NULL;
    hash = malloc(cnt);

    memset(hash, 1, cnt);
    printf("Hello, World!\n");

    for(i=0; i<cnt; i++)
        printf("%d ", hash[i]);

    return 0;
}

Sortie:

Bonjour le monde!
1 1 1 1 1 

0
akD

J'ai essayé le programme suivant et il semble que vous puissiez initialiser votre tableau en utilisant memset () avec -1 et 0 uniquement 

#include<stdio.h>
#include<string.h>

void printArray(int arr[], int len)
{
        int i=0;
    for(i=0; i<len; i++)
    {
        printf("%d ", arr[i]);
    }
    puts("");
}

int main()
{
    int arrLen = 15;
    int totalNoOfElementsToBeInitialized = 6;

    int arr[arrLen];
    printArray(arr, arrLen);
    memset(arr, -1, totalNoOfElementsToBeInitialized*sizeof(arr[0]));
    printArray(arr, arrLen);
    memset(arr, 0, totalNoOfElementsToBeInitialized*sizeof(arr[0]));
    printArray(arr, arrLen);
    memset(arr, 1, totalNoOfElementsToBeInitialized*sizeof(arr[0]));
    printArray(arr, arrLen);
    memset(arr, 2, totalNoOfElementsToBeInitialized*sizeof(arr[0]));
    printArray(arr, arrLen);
    memset(arr, -2, totalNoOfElementsToBeInitialized*sizeof(arr[0]));
    printArray(arr, arrLen);
    return 0;
}
0
ganjaam