1

わかりました、まず最初に、私は C とポインター (Java プログラマー) に非常に慣れていないので、優しくしてください。このクラスでは、Syscall の使用のみが許可されているため、stdio は使用できません。

この関数は、入力として C 文字列を void* として受け取り、それを追加する必要があるメモリ内の領域を指す別の void* を受け取ります。何らかの理由で、新しい場所に適切に配置されていません。

*(char*)ptr = (char*)data;

ptr は void* であり、文字列を書き込みたいメモリ内の場所であり、 data はそこに書き込みたい文字列である void* です。

これら 2 つの値を出力すると、(char*)data を呼び出したときに正しい文字列が得られますが、(char*)ptr を出力すると文字化けが発生するだけです。上記の行を次のように変更すると:

*(char*)ptr = *(char*)data;

次に、文字列の最初の文字だけがそこのメモリに入ります。

私は何を間違っていますか?

ありがとう。

完全なソース:

#include <stdlib.h>
#include <unistd.h>

#define F_first         1 //First call to function, allocate amount of memory specified by data
#define F_last          2 //last call to function, free memory area
#define F_data_int      3 //void* arg points to integer data
#define F_data_char     4 //void* arg points to character string
#define F_data_float    5 //void* arg points to float data
#define F_print         6 //print the accumulated values in memory

#define Ptr_offset      32 //the amount of extra data I'm setting aside to store info about how much total data is allocated and how much of that area is being used

void* f( int code, void* mem, void* data )
{
    size_t totalSize = 500;
    size_t dataSize = 0;
    size_t availableSize = 0;
    size_t neededSize = 0;
    void* ptr;

    if( code == F_first )
    {

        if( mem != NULL )
        {
            exit(1);
        }

        if( data != NULL )
        {
            totalSize = (size_t)data + Ptr_offset;
            mem = malloc( totalSize );

        }else{
            totalSize += Ptr_offset;
            mem = malloc( totalSize );
        }

        dataSize = 0;
    }
    else if( code == F_last )
    {
        if( mem == NULL )
        {
            exit(1);
        }
        else
        {
            free( mem );
        }

    }
    else if( code == F_data_int )
    {
        dataSize = *(int*)(mem + (Ptr_offset/2));
        totalSize = *(int*)mem;
        availableSize = totalSize - dataSize;
        neededSize = sizeof(*(int*)data);

        if( neededSize >= availableSize )
        {
            totalSize = neededSize * 2;
            mem = realloc(mem, totalSize);
        }

        ptr = mem + Ptr_offset + dataSize;
        *(int*)ptr = *(int*)data;

        ptr = mem + Ptr_offset/2;
        *(int*)ptr = dataSize+sizeof(*(int*)data);

    }
    else if( code == F_data_char )
    {
        dataSize = *(int*)(mem + (Ptr_offset/2));
        totalSize = *(int*)mem;
        availableSize = totalSize - dataSize;
        neededSize = sizeof(*(char*)data);

        if( neededSize >= availableSize )
        {
            totalSize = neededSize * 2;
            mem = realloc(mem, totalSize);
        }

        ptr = mem + Ptr_offset + dataSize;
        strcpy(ptr, data);

        printf("\n chardata: %s \n charptr: %s \n", (char*)data, (char*)ptr);

        ptr = mem + Ptr_offset/2;
        *(int*)ptr = dataSize+sizeof(*(char*)data);

    }else if( code == F_data_float )
    {
        dataSize = *(int*)(mem + (Ptr_offset/2));
        totalSize = *(int*)mem;
        availableSize = totalSize - dataSize;
        neededSize = sizeof(*(float*)data);

        if( neededSize >= availableSize )
        {
            totalSize = neededSize * 2;
            mem = realloc(mem, totalSize);
        }

        ptr = mem + Ptr_offset + dataSize;
        *(float*)ptr = *(float*)data;

        ptr = mem + Ptr_offset/2;
        *(int*)ptr = dataSize+sizeof(*(float*)data);

    }else if( code == F_print )
    {
        ptr = mem + Ptr_offset/2;
        write(1, ptr, *(int*)mem);
    }

    if(mem != NULL)
    {
        *(int*)mem = totalSize;
    }

    return mem;
}

int main( void )
{
    int i_a;
    float f_a;

    void* m;
    int* i;
    float* fl;

    fl = &f_a;
    i = &i_a;

    m = f( F_first, 0, (void*)300 );
    m = f( F_data_char, m, (void*)"Systems programming class has " );

    f_a = 69.7;
    m = f( F_data_float, m, (void*)fl );
    m = f( F_data_char, m, (void*)"registered " );
    m = f( F_data_char, m, (void*)"students in a " );
    m = f( F_data_char, m, (void*)"classroom of " );

    i_a = 70;
    m = f( F_data_int, m, (void*)i );
    m = f( F_data_char, m, (void*)"\n" );

    m = f( F_print, m, 0 );

    m = f(F_last, m, 0);

    return 0;
}
4

3 に答える 3

1

コードを持っているので、フォローするのが難しいので、さまざまな関数に対して個別の関数を作成すると役立ちます。

割り当てたメモリを0に初期化せずに、合計などを読み取ります。

0で割り当てるまたは0でcalloc行うために使用しますmemset

また、代わりに、バッファのメモリレイアウトを記述する構造体を作成した場合にも役立ちます。そうすれば、オフセットをいじる必要はありません。

例えば

struct foo
{
  size_t totalSize;
  size_t currentSize;
  ...   
  char buf[];
};

mem = calloc( 1, sizeof( struct foo ) + bufSize);
于 2013-02-03T22:44:25.973 に答える
1

関数の外で宣言されたオブジェクトに割り当てたい場合は、オブジェクトへのポインターを渡す必要があります。これは、呼び出される関数が、実際のオブジェクトではなく、渡されたオブジェクトのコピーを受け取るためです。例えば:

void incorrect(char c) { c = 42; }
void corrected(char *c) { *c = 42; }
int main(void) {
    char c = 0;
    incorrect(c); // As is demonstrated by printing the integer value of c, incorrect doesn't get the job done
    printf("c after incorrect: %d\n", c);
    corrected(&c);
    printf("c after corrected: %d\n", c);
}

corrected(&c);変更したいオブジェクトへのポインターを渡す方法をコードに書き留めてください。変更したいオブジェクトへのポインターをどこに渡していますか?

これを拡張して、ポインターに代入してみましょう。

void assign(char **ptr, char *newval) { *ptr = newval; }
int main(void) {
    char *ptr = NULL;
    assign(&ptr, malloc(42));
    assert(ptr != NULL); // One would assume ptr has changed.
}

繰り返しますが、&ptr は、変更したいオブジェクトへのポインターであることに注意してください。これを拡張して、 a が指すポインタに代入しますvoid *

void assign(void *ptr, char *newval) { *(char **)ptr = newval; }
int main(void) {
    char *ptr = NULL;
    assign(&ptr, malloc(42));
    assert(ptr != NULL); // One would assume ptr has changed.
}

ptr は型情報を失いましたが、変更したいオブジェクトへのポインターである &ptr をまだ渡しています。それを変更するには、void *back をにキャストし、割り当て可能な左辺値を形成する をchar **逆参照する必要があります。char **

于 2013-02-03T22:39:24.860 に答える
1

strcpyまたはそのより安全なバリアントを使用strncpyして、文字列をコピーします。C では配列を割り当てることができません。

strcpy(ptr, data);

あなたのコードについて:

*(char*)ptr = (char*)data;

=これは有効な C ではありません。演算子の左側には typecharがあり、右側には type がありchar *ます。char *を に割り当てることはできませんchar

于 2013-02-03T21:58:18.480 に答える