1

好的,首先我是 C 新手,并且对指针(Java 程序员)非常陌生,所以请保持温和。对于这个类,我只允许使用 Syscalls,所以没有 stdio。

该函数接收一个 C 字符串作为 void* 的输入,另一个 void* 指向我需要将其添加到的内存区域。无论出于何种原因,它都没有正确地放入新位置。

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

ptr 是一个 void* 并且是我想要将字符串写入到的内存中的位置,而 data 是一个 void* 是我想要在那里写入的字符串。

如果我打印出这两个值,我会在打印 (char*) 数据时得到正确的字符串,但在打印 (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

使用strcpy或其更安全的变体strncpy来复制字符串。您不能在 C 中分配数组。

strcpy(ptr, data);

关于您的代码:

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

这不是有效的 C,=运算符的左侧有 type char,右侧有 type char *。您不能将 a 分配char *给 a char

于 2013-02-03T21:58:18.480 回答
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 转换为 a char **,取消引用char **形成我可以分配的左值。

于 2013-02-03T22:39:24.860 回答
1

如果您为不同的功能创建了单独的功能,这将有所帮助,因为您现在拥有难以遵循的代码。

您不会将分配的内存初始化为 0,然后继续从中读取总数等。

用于calloc分配或memset使用 0

如果您改为创建一个描述缓冲区内存布局的结构,也会有所帮助。这样你就不需要摆弄偏移量。

例如

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

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