Указатель литья в C - PullRequest
       13

Указатель литья в C

0 голосов
/ 12 августа 2010
static int write_stream(const void *buffer, size_t size, void *app_key) 
{
    char *stream = (char *)app_key;

    return 0;
}

Почему приведение указателя делает не приводит к копированию байтов (size_t size) из буфера в поток определяется app_key?

Спасибо

Редактировать: Я вызываю эту функцию как аргумент другой функции для использования обратного вызова:

static int write_stream(const void *buffer, size_t size, void *app_key) 
{
    char *stream = (char *)app_key; 
    return 0;
}

int print_to_2buf(char *ostream, struct asn_TYPE_descriptor_s *td, void *struct_ptr)
{
    asn_enc_rval_t er; /* Encoder return value */

    // write_stream is called as argument
    er = xer_encode
    (
        td,
        struct_ptr,
        XER_F_BASIC,
        /* BASIC-XER or CANONICAL-XER */ write_stream,
        ostream
    );

    return (er.encoded == -1) ? -1 : 0; 
}

Ответы [ 5 ]

4 голосов
/ 12 августа 2010

Все, что вы сделали - создали указатель на символ, который содержит тот же адрес, что и указатель на void, который вы получили.Вы ничего не сделали для копирования байтов из app_key в buffer, поэтому ничего не копируется.Если я не правильно понял вопрос, вы, вероятно, должны просто использовать memcpy или memmove.

3 голосов
/ 12 августа 2010

Из вашего вопроса я не могу быть уверен в вашем уровне понимания, но похоже, что вы не знакомы с механикой указателей, поэтому я постараюсь дать быстрое объяснение.

ВашПараметр void * app_key - это целое число, которое хранит местоположение в памяти блока неизвестного (void) типа.

Ваш поток char * также является целым числом, он хранит местоположение в памяти блока типа char(либо один символ, либо первый символ в непрерывном блоке).

Ваша строка кода char *stream = (char *)app_key копирует целочисленное значение app_key (то есть адрес в памяти, на который ссылается app_key) и сохраняетон также находится в потоке.

На этом этапе и app_key, и stream хранят одно и то же место в памяти - адрес первого символа в вашем app_key (при условии, что в качестве параметра передана строка).

Однако поймите, что единственное, что было скопировано, это целочисленный адрес памяти вашего app_key.До сих пор есть только одна копия.

То, что вы хотели сделать, это создать новую копию строки app_key, которая была сохранена в другом месте в памяти (возможно, когда функциявозвращается, и исходная строка уничтожается, у вас все еще есть копия).

Чтобы сделать это, вам нужно сделать следующее:

1: allocate memory space sufficient to hold the new copy
2: copy all of the characters from the original to the copy

Есть много способов сделать это в зависимости отна то, что ваши потребности.Вот один из них:


static int 
write_stream (const void *buffer, size_t size, void *app_key) 
{
    //create a memory buffer large enough to hold size_t size chars.
    char *stream = (char *)malloc(sizeof(char) * size);

    //copy size_t size chars from location at app_key to location at stream
    memcpy(stream, app_key, sizeof(char) * size);

    //rest of your function
}

Поскольку вы работаете со строками, вы также можете использовать функцию strcpy () (возможно, в паре с strlen).Все эти функции предполагают, что вы используете строку с нулевым символом в конце (то есть строка представляет собой последовательность char s, с конечным \0 в конце, указывающим конец.

1 голос
/ 12 августа 2010

Когда вы используете указатель, у вас есть ссылка на некоторый тип в памяти.Это как положить палец на квадрат на игровой доске.Вы можете взять другой палец (в данном случае поток указателя на символ) и положить его на тот же квадрат.Теперь у вас есть два указателя на один и тот же квадрат.Это не превращает ваши пальцы в игровые квадраты.Вам нужно сделать какую-то другую работу, чтобы сделать копию того объекта, на который указывает указатель, например мемкопию.

1 голос
/ 12 августа 2010

Почему вы думаете, что это будет? С одной стороны, char *stream = (char *)app_key не упоминает size везде, так почему его поведение зависит от значения size? С другой стороны, вы просто превращаете указатель в другой указатель: ничто в вашем коде не говорит о том, что вы хотите разыменовать указатель и скопировать то, на что он указывает.

Чтобы скопировать size байт, откуда buffer указывает, куда app_key указывает, используйте функцию memcpy (вам нужно #include <string.h>).

memcpy(app_key, buffer, size);

Вы должны убедиться, что в app_key достаточно места, то есть app_key должно указывать на выделенную область памяти, размер которой по крайней мере size. Это может быть достаточно большой массив в вызывающей функции или память, выделенная с помощью malloc.

Обратите внимание, что приведения должны использоваться только тогда, когда вы знаете, что делаете. В частности, почти никогда не нужно приводить указатель к void*.

1 голос
/ 12 августа 2010

Поскольку приведение только интерпретирует данные, оно не делает (или должно) копировать.

Кроме того, как актер знает, что он должен делать копию байтов размера? Вы предполагаете слишком много из простого броска. Сделайте копию самостоятельно.

(я полагаю, вы вставили правильный код).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...