2017-12-07 15 views
2

以下に、問題を示す簡単なCプログラムがあります。ポインタを使用してreallocにコールしようとするとうまくいきますが、ポインタにオフセットを追加しようとすると(つまり、配列の後の要素から開始する)、失敗します。ポインタにオフセットがあるとreallocがクラッシュする

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

struct arbNum{ 
    unsigned char* bytes; 
    long len; 
}; 

void trim(struct arbNum* num){ 
    printf("%d,%d,%d,%d\n",num->bytes,num->bytes[0],num->bytes[1],num->len); 
    unsigned char* nbytes = realloc(num->bytes,num->len); 
    printf("Realloc successful.\n"); 
    num->bytes = nbytes; 
} 

int main(void){ 
    struct arbNum p = {calloc(2,1),2}; 
    trim(&p); 
} 
例として

、この出力:

9247152,0,0,2 
Realloc successful. 

しかし、上記のコードから、realloc(num->bytes+1,num->len-1);realloc(num->bytes,num->len);を変更すると、この出力/動作を変更し:次いで

10361264,0,0,2 

やクラッシュ。私はポインタを全く理解していないかもしれませんが、私の現在の理解は、それらが基本的に別の値が格納されているアドレスであるということです。この場合、なぜpointer+1がポインタよりも1つ高いアドレスに格納されている値を指していないか、言い換えれば、そのポインタが指す配列の最初の要素として機能するのはなぜですか?私がしようとしているのは、num.bytesが指し示す配列を最初の要素からメモリ内の新しいアドレスにコピーすることですが、明らかに何らかの理由で失敗しています。

答えて

7

いいえ、あなたはmalloc()またはファミリによって以前に返された実際のポインタでrealloc()しかできません。

そうでない場合、それは、C11を引用undefined behavior

だ章§7.22.3.5

ptrがNULLポインタである場合は、realloc機能は 指定したサイズのためにmalloc機能のように振る舞います。そうでない場合、ptrがメモリ 管理関数によって返されたポインタと一致しない場合、またはfreeまたは realloc関数の呼び出しによって領域が割り当て解除された場合、その動作は未定義です。 [...]

だから、あなたはは意味をなさないこと、は、新しいアドレスを生成行くrealloc()にそれを渡すと、部分的に再割り当てすることを期待aritmaticポインタを使用することを許可されていません。

+0

右。そして、明らかに私が望むことをするために 'memcpy'を使うことができます。 – user2649681

+0

@ user2649681まあ、それ以前でさえ、あなたはUBにぶつかるでしょう。 –

+0

@ user2649681 "明らかに私はmemcpyを使って私が望むことをすることができます" - >疑わしい。しかし、 'memmove()'がうまくいくかもしれません。 – chux

関連する問題