5

cスタイルの文字列では、文字ポインタが指すメモリアドレスにcharをどのように割り当てますか?たとえば、次の例では、numを「123456」に変更したいので、pを「0」のある数字に設定して「4」で上書きしようとしました。ありがとう。

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char* num = (char*)malloc(100);
    char* p = num;

    num = "123056";

    p = p+3;    //set pointer to where '4' should be
    p = '4';

    printf("%s\n", num );

    return 0;
}
4

5 に答える 5

13

まず第一に、あなたがするとき:

num = "123056";

によって割り当てられたヒープの領域に文字列「123056」をコピーしていませんmalloc()。Cでは、char *ポインタに文字列リテラル値を割り当てることは、それを定数として設定することと同じです。つまり、次のようになります。

char str[] = "123056";

したがって、ここで達成したのは、によって割り当てられた100バイトのヒープ領域への唯一の参照を放棄したことです。malloc()これが後続のコードが正しい値を出力しない理由です。' 'は、 (割り当て時にポイントされたため)pによって割り当てられたヒープの領域をポイントしますが、もはやポイントしません。malloc()numnum

実際に意図したのは、文字列「123056」をそのヒープ領域にコピーすることだったと思います。その方法は次のとおりです。

strcpy(num, "123056");

ただし、これはさまざまな理由からより適切な方法です。

strncpy(num, "123056", 100 - 1);  /* leave room for \0 (null) terminator */

行ったばかりの場合:

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

int     main(void) {
        char    *num = malloc(100);
        char    *p = num;

        strncpy(num, "123056", 100 - 1);

        p = p + 3;
        *p = '4';

        printf("%s\n", num);

       return 0;
} 

あなたは正しい結果を得たでしょう:

123456

この操作を契約できます。

p = p + 3;
*p = '4';

...そして、次のように延期することにより、ポインタの反復を避けます。

*(p + 3) = '4';

他のいくつかの注意:

  • malloc()一般的なスタイルの慣習ですが、 toの戻り値をキャストする(char *)必要はありません。タイプの変換と整列はvoid *、C言語によって保証されています。

  • の戻り値を常に確認してくださいmalloc()。ヒープの割り当てに失敗した場合(つまり、メモリが不足している場合)はNULLになり、その時点でプログラムを終了する必要があります。

  • 実装によっては、によって割り当てられたメモリの領域にmalloc()、特定の状況で古いガベージが含まれる場合があります。割り当て後にゼロにすることは常に良い考えです:

    memset(num, 0, 100);
    
  • free()あなたのヒープを決して忘れないでください!この場合、プログラムは終了し、OSはごみをクリーンアップしますが、習慣に従わないと、すぐにメモリリークが発生します。

したがって、これが「ベストプラクティス」バージョンです。

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

int     main(void) {
        char    *num, *p;

        /*
         * Don't take 1-byte chars for granted - good habit to get into.
         */

        num = malloc(sizeof(char) * 100);

        if(num == NULL)
                exit(1);

        memset(num, 0, sizeof(char) * 100);

        p = num;

        strncpy(num, "123056", 100 - 1);

        *(p + 3) = '4';

        printf("%s\n", num);

        free(num);

        return 0;
}
于 2009-06-03T05:35:09.303 に答える
12

次の行があるため、そのコードは機能しません。

num = "123056";

num割り当てられたメモリから離れた場所を指すように変更します(そしてp、そのメモリを指し続けるため、それらは同じ場所ではなくなります)、最も可能性の高い読み取り専用メモリです。文字列リテラルに属するメモリを変更することは許可されていません。これは未定義の動作です。

次のものが必要です。

#include <stdio.h>
#include <stdlib.h>
int main (void) {
    char *num = malloc (100); // do not cast malloc return value.
    char *p = num;

    strcpy (num, "123056");   // populate existing block with string.

    p = p + 3;                // set pointer to where '0' is.
    *p = '4';                 // and change it to '4'.

    printf ("%s\n", num );    // output it.

    return 0;
}
于 2009-06-03T05:40:11.573 に答える
1

他の人が指摘している*pの問題に加えて、メモリ使用量の問題もあります。内容が不明な100バイトのバッファが1つあります。文字列「123056」とヌルターミネータを含む7バイトの別のバッファがあります。あなたはこれをやっています:

  1. numは、100バイトのバッファーを指すように設定されます
  2. pはnumを指すように設定されています。つまり、100バイトのバッファを指します
  3. numをリセットして7バイトのバッファを指すようにします。pはまだ100バイトのバッファを指しています
  4. pを使用して100バイトのバッファを変更します
  5. 次に、numを使用して7バイトのバッファを出力します

したがって、変更しているのと同じバッファを出力していません。

于 2009-06-03T05:38:37.457 に答える
0

使用するだけ*p = '4';です...!

于 2009-06-03T05:32:04.193 に答える
0

さて、あなたはpがポインタ型であることを知っています。文字「0」のアドレスを格納します。pに「4」の値を割り当てる場合。アドレスは「4」になります。ただし、アドレス「4」は不正です。'*'演算子を使用して、pstoredに格納されているアドレスの値を取得できます。

于 2009-06-03T05:36:53.453 に答える