web-dev-qa-db-ja.com

Cの整数配列にmemsetを使用する

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

output:
******ful earth

1)上記のmemsetの使用と同様に、以下に示すように、少数の整数配列インデックス値のみを1に初期化できますか?

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

いいえ、このようにmemset()を使用することはできません。 manpage は(emphasis mine)と言います:

memset()関数は、nが指すメモリ領域の最初のsbytesを埋めます。定数バイトcを使用します。

intは通常4バイトなので、これはカットしません。


もし(incorrectly !!)これを試してください:

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

配列の最初の6 intsは、実際には0x01010101 = 16843009に設定されます。

バイト以外のデータ型でデータの「ブロブ」を上書きすることが本当に受け入れられるのは、memset(thing, 0, sizeof(thing));が構造体/配列全体を「ゼロアウト」することだけです。これは、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.
_
41

短い答え、NO。

長い答え、memsetはバイトを設定し、単一バイトであるため文字に対して機能しますが、整数はそうではありません。

13
vidit

Memsetの3番目の引数はバイトサイズです。したがって、合計バイトサイズを_arr[15]_に設定する必要があります

_memset(arr, 1, sizeof(arr));
_

ただし、おそらく、arrの要素全体に値1を設定する必要があります。その後、ループで設定する方が良いでしょう。

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

memset()は各バイトに1を設定するためです。だからそれはあなたの期待ではありません。

3
mattn

Linux、OSX、およびオペレーティングシステムのような他のUNIXでは、_wchar_t_は32ビットであり、wmemset()の代わりにmemset()を使用できます。

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

MS-Windowsの_wchar_t_は16ビットであるため、このトリックは機能しない場合があります。

3
ceilingcat

いいえ、目的のターゲット値が0でない限り、その目的で[ポータブル] memsetを使用することはできません。 memsetは、ターゲットメモリ領域をintsの配列ではなく、バイトの配列として扱います。

メモリ領域を繰り返しパターンで埋めるためのかなり人気のあるハックは、実際にはmemcpyに基づいています。 memcpyがデータを順方向にコピーするという期待に大きく依存しています

int arr[15];

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

もちろん、これはかなりprettyいハックです。なぜなら、ソースとデスティネーションのメモリ領域がオーバーラップするときの標準のmemcpyの振る舞いは未定義だからです。ただし、memcpyの独自のバージョンを作成して、データを順方向にコピーし、上記の方法で使用することができます。しかし、それは本当に価値がありません。単純なサイクルを使用して、配列の要素を目的の値に設定するだけです。

1
AnT

Memsetは1バイトのデータ型に値を設定しますが、整数には4バイト以上ありますので、機能せず、ガベージ値を取得します。主にchar型とstring型を使用しているときに使用されます。

0

誰も言及していないので...

Memsetを使用して整数を値1で初期化することはできませんが、canを値-1で初期化し、代わりに負の値で動作するようにロジックを変更します。

たとえば、配列の最初の6つの数字を-1で初期化するには、次のようにします。

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

さらに、この初期化を一度だけ行う必要がある場合は、コンパイル時に値1で始まる配列を実際に宣言できます。

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

理想的には、memsetを使用して、すべてを1に設定することはできません。
memsetはバイトに対して機能し、すべてのバイトを1に設定するためです。

memset(hash, 1, cnt);

そのため、一度読み取ると、表示される値16843009 = 0x01010101 = 1000000010000000100000001
Not x00000001
ただし、requiremntがboolまたはバイナリ値のみの場合は、CライブラリのC99標準を使用して設定できます

#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;
}

出力:

こんにちは世界!
1 1 1 1 1

0
akD

私は次のプログラムを試してみましたが、-1と0のみでmemset()を使用して配列を初期化できるようです

#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