Search code examples
cpointersc-strings

(homework) How to put a C-string from one pointer into the memory address of another pointer?


Okay, first off I'm new to C and very new to pointers (Java programmer), so please be gentle. For this class I'm only allowed to use Syscalls, so no stdio.

This function is receiving as input a C-string as a void*, and another void* that points to the area in memory I need to add it to. For whatever reason it's not properly getting put into the new location.

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

ptr is a void* and is the location in memory I want to write the string to, and data is a void* that is the string I want to write there.

If I print out these two values, I get the correct string when pringing (char*)data, but I just get a garbage character when printing (char*)ptr. If I change the above line to:

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

Then only the first character of the string goes into the memory there.

What am I doing wrong?

Thanks.

Full Source:

#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;
}

Solution

  • Use strcpy or its safer variant strncpy to copy a string. You cannot assign arrays in C.

    strcpy(ptr, data);
    

    Regarding your code:

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

    This is not valid C, the left side of the = operator has type char and the right side has type char *. You cannot assign a char * to a char.