2010-08-12 4 views
0
static int write_stream(const void *buffer, size_t size, void *app_key) 
{ 
    char *stream = (char *)app_key; 

    return 0; 
} 

Почему литье указатель делает не приводит к копированию (размер size_t) байт из буфера в потока, определенного app_key?Указатель литья в C

Благодаря

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

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; 
} 
+0

Как это называется? –

+1

Не могли бы вы пожалуйста, опишите, что должен делать код? – stacker

ответ

3

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

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

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

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

На этом этапе как app_key, так и поток хранят одно и то же местоположение в памяти - адрес первого символа в вашей 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 
} 

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

+0

ok Спасибо за вашу помощь. – Said

1

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

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

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

4

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

1

Почему вы думаете, что это будет? Во-первых, 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

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

Смежные вопросы