13

文字列サイズが6のmallocを呼び出すと、4バイトのサイズが返される理由を誰かが説明できますか?実際、mallocに指定した整数引数のサイズは4になります。次に、2つの文字列をコピーしようとしています。コピーされた文字列(NULL)の出力がなぜですか?以下は私のコードです:

int main()
{
    char * str = "string";
    char * copy = malloc(sizeof(str) + 1);
    printf("bytes allocated for copy: %d\n", sizeof(copy));
    while(*str != '\0'){
        *copy = *str;
        str++;
        copy++;
    }
    copy = '\0';
    printf("%s\n", copy);
}
4

8 に答える 8

20

sizeof(str)タイプのポインタのサイズを返しますchar*。あなたがすべきことはmalloc、それ自体が文字列のサイズになることです。

char * copy = malloc(strlen(str) + 1);

また、これらの行:

while(*str != '\0'){
        *copy = *str;
        str++;
        copy++;
}
copy = '\0';

次のようにCで簡単に書き直すことができます。

while(*copy++ = *str++);
于 2009-10-07T19:01:58.770 に答える
5

まず、 sizeof (xxx)(xxxは任意の左の値の式(​​変数))は、do sizeofタイプxxx )と常に同等であることを理解する必要があります。したがって、実際にsizeof(str)を実行しているのは、char *のサイズ、つまり他のポインターのサイズを返すことです。32ビットアーキテクチャでは4になり、64ビットアーキテクチャでは8になります。

したがって、他の人も説明しているように、割り当てる文字列の長さを知ってから、1を追加して端末\ 0を格納する必要があります。Cは、文字列の最後に置くために暗黙的に使用します。

しかし、必要なこと(文字列をコピーして必要なスペースを割り当てる)を実行するには、 strdupを使用する方が簡単で効率的です。これは、まさにそれを実行します:mallocstrcopy

また、自分で割り当てたスペースを解放することも忘れないでください(malloc、calloc、strdup、またはその他の割り当て関数を使用)。Cでは、割り当てられた変数がスコープ外になっても消えません。プログラムが終了するまで使用され続けます。それはあなたがメモリリークと呼ぶものです。

#include <string.h> /* for strdup, strlen */
#include <stdio.h> /* for printf */

int main()
{
    char * str = "string";
    char * copy = strdup(str);
    printf("bytes at least allocated for copy: %d\n", strlen(copy)+1);
    printf("%s\n", copy);
    free(copy);
}

最後のポイント:mallocを呼び出すときに割り当てられたサイズがよくわからないため、メッセージを少なくとも割り当てられたバイトに変更しました。多くの場合、要求したスペースよりもわずかに多くのスペースが割り当てられます。多くのメモリマネージャでは、空きブロックは非表示のデータ構造を使用してリンクされており、割り当てられたブロックには少なくともそのような構造を含めることができる必要があります。別の理由は、割り当てられたブロックが常に任意のタイプと互換性があるように配置されることです。アラインメント。

Cをもう少しよく理解するのに役立つことを願っています。

于 2009-10-07T20:13:25.900 に答える
3

あなたはそれが指しているものではなく、strポインタのサイズ(4バイト)を取得していますか?

于 2009-10-07T19:01:45.500 に答える
3

sizeof(str)文字列自体ではなく、文字列へのポインタを格納するために必要なスペースを返します。strlen(str)たとえば、文字列のサイズを確認できます。

copy次に、値0(文字)を持つ整数へのポインターに影響を与えます'\0'。これは、printf()関数が表示するものと同じcopy = NULLです。

于 2009-10-07T19:04:17.380 に答える
2

sizeof()は、変数の実際の型のサイズを返します。したがって、型をchar *として定義すると、ポインターのサイズが返されます。

ただし、変数を配列にした場合、sizeofは配列自体のサイズを返します。これにより、必要な処理が実行されます。

char *ptr = "moo to you";
char arr[] = "moo to you";

assert(sizeof(ptr) == 4);   // assuming 32 bit
assert(sizeof(arr) == 11);  // sizeof array includes terminating NUL
assert(strlen(arr) == 10);  // strlen does not include terminating NUL
于 2009-10-07T19:45:54.053 に答える
1

2番目の質問に取り組むには、ステートメントcopy++を実行することにより、の値copy(つまり、char配列を保持するメモリ内のアドレス)を変更して、出力するまでに、配列ではなく配列の最後を指すようにします。始まり(によって返される値malloc())。文字列を更新し、文字列の先頭にアクセスできるようにするには、追加の変数が必要になります。

問題を修復するために編集malloc/sizeofします-CLに感謝します。

char * str = "string";
/*   char * copy = malloc(sizeof(str) + 1);  Oops  */
char * copy = malloc(strlen(str) + 1);
char * original_copy = copy;
printf("bytes allocated for copy: %d\n", sizeof(copy));
while(*str != '\0'){
    *copy = *str;
    str++;
    copy++;
}
copy = '\0';
printf("%s\n", original_copy);
于 2009-10-07T19:09:41.407 に答える
1
  • sizeof()は、割り当てられたバイト数ではなく、ポインタのサイズを返します。割り当てられたバイトをカウントする必要はありません。返されたポインタがではないかどうかを確認するだけですNULL
  • copy = '\0'; ポインタをリセットして作成しNULLます。
于 2009-10-07T19:47:35.950 に答える
-1

次を使用できます。

size_t malloc_usable_size(void * ptr);

の代わりに:sizeof

ただし、割り当てられたメモリブロックの実際のサイズが返されます。あなたがmallocに渡したサイズではありません!

于 2014-01-17T11:51:37.450 に答える