Консультация № 200938
24.05.2021, 10:18
0.00 руб.
0 5 1
Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос:
Код написан на СИ. Прошу прокомментировать работу с указателем массива. Вопросы и мои мысли в коде.
Код:

void load_src( long * Error_Flag, char ** Error_Type,
SIGNAL_INFO * sinfo)
{
long name_len;
long file_size;
long header_size = 0;
long Nsamples;
long to_read;
long read_count;
long count;

float *read_ptr; // тут мы создаем указатель на адрес в памяти
short *input_data;
short *p_input;
char s;
char *p_byte;
FILE *Src_file = fopen( sinfo-> path_name, "rb" );

input_data = (short *) safe_malloc( 16384 * sizeof(short) );
if( input_data == NULL )
{
*Error_Flag = 1;
*Error_Type = "Could not allocate storage for file reading";
printf ("%s!\n", *Error_Type);
fclose( Src_file );
return;
}

if( Src_file == NULL )
{
*Error_Flag = 1;
*Error_Type = "Could not open source file";
printf ("%s!\n", *Error_Type);
safe_free( input_data );
return;
}

if( fseek( Src_file, 0L, SEEK_END ) != 0 )
{
*Error_Flag = 1;
*Error_Type = "Could not reach end of source file";
safe_free( input_data );
printf ("%s!\n", *Error_Type);
fclose( Src_file );
return;
}
file_size = ftell( Src_file );
if( file_size < 0L )
{
*Error_Flag = 1;
*Error_Type = "Could not measure length of source file";
safe_free( input_data );
printf ("%s!\n", *Error_Type);
fclose( Src_file );
return;
}
if( fseek( Src_file, 0L, SEEK_SET ) != 0 )
{
*Error_Flag = 1;
*Error_Type = "Could not reach start of source file";
safe_free( input_data );
printf ("%s!\n", *Error_Type);
fclose( Src_file );
return;
}
name_len = strlen( sinfo-> path_name );
if( name_len > 4 )
{
if( strcmp( sinfo-> path_name + name_len - 4, ".wav" ) == 0 )
header_size = 22;
if( strcmp( sinfo-> path_name + name_len - 4, ".WAV" ) == 0 )
header_size = 22;
if( strcmp( sinfo-> path_name + name_len - 4, ".raw" ) == 0 )
header_size = 0;
if( strcmp( sinfo-> path_name + name_len - 4, ".src" ) == 0 )
header_size = 0;
}
if( name_len > 2 )
{
if( strcmp( sinfo-> path_name + name_len - 2, ".s" ) == 0 )
header_size = 0;
}

if( header_size > 0 )
fread( input_data, 2, header_size, Src_file );

Nsamples = (file_size / 2) - header_size;
sinfo-> Nsamples = Nsamples + 2 * SEARCHBUFFER * Downsample;

sinfo-> data =
(float *) safe_malloc( (sinfo-> Nsamples + DATAPADDING_MSECS * (Fs / 1000)) * sizeof(float) );
if( sinfo-> data == NULL )
{
*Error_Flag = 1;
*Error_Type = "Failed to allocate memory for source file";
safe_free( input_data );
printf ("%s!\n", *Error_Type);
fclose( Src_file );
return;
}

read_ptr = sinfo-> data; // Тут получаем ссылку на 0 элемент массива в структуре. data - это массив float.
for( read_count = SEARCHBUFFER*Downsample; read_count > 0; read_count-- )
*(read_ptr++) = 0.0f; // Tут мы проходимся по массиву и заполняем его нулями.
// С 0 элемента массива. Количество циклов равно SEARCHBUFFER*Downsample - 1.
// В результате read_ptr ссылается на (SEARCHBUFFER*Downsample - 1) элемент массива

to_read = Nsamples;
while( to_read > 16384 )
{
read_count = fread( input_data, sizeof(short), 16384, Src_file );
if( read_count < 16384 )
{
*Error_Flag = 1;
*Error_Type = "Error reading source file.";
printf ("%s!\n", *Error_Type);
safe_free( input_data );
safe_free( sinfo-> data );
sinfo-> data = NULL;
fclose( Src_file );
return;
}
if( sinfo-> apply_swap )
{
p_byte = (char *)input_data;
for( count = 0L; count < read_count; count++ )
{
s = p_byte[count << 1];
p_byte[count << 1] = p_byte[(count << 1)+1];
p_byte[(count << 1)+1] = s;
}
}
to_read -= read_count;
p_input = input_data;
while( read_count > 0 )
{
read_count--;
*(read_ptr++) = (float)(*(p_input++)); // Тут read_ptr ссылается на (SEARCHBUFFER*Downsample - 1) элемент массива.
// В результате работы цикла read_ptr будет ссылаться уже на (SEARCHBUFFER*Downsample - 1 + read_count).
// Или он ссылался на 0 и увеличился на read_count?
}
}
read_count = fread( input_data, sizeof(short), to_read, Src_file );
if( read_count < to_read )
{
*Error_Flag = 1;
*Error_Type = "Error reading source file";
printf ("%s!\n", *Error_Type);
safe_free( input_data );
safe_free( sinfo-> data );
sinfo-> data = NULL;
fclose( Src_file );
return;
}
if( sinfo-> apply_swap )
{
p_byte = (char *)input_data;
for( count = 0L; count < read_count; count++ )
{
s = p_byte[count << 1];
p_byte[count << 1] = p_byte[(count << 1)+1];
p_byte[(count << 1)+1] = s;
}
}
p_input = input_data;
while( read_count > 0 )
{
read_count--;
*(read_ptr++) = (float)(*(p_input++)); // Тут read_ptr ссылается на (SEARCHBUFFER*Downsample - 1 + read_count) элемент массива.
// В результате работы цикла read_ptr будет ссылаться уже на (SEARCHBUFFER*Downsample - 1 + read_count + (new)read_count).
// Или он ссылался на 0 и увеличился на read_count?
}

for( read_count = DATAPADDING_MSECS * (Fs / 1000) + SEARCHBUFFER * Downsample;
read_count > 0; read_count-- )
*(read_ptr++) = 0.0f; // Тут read_ptr ссылается на (SEARCHBUFFER*Downsample - 1 + read_count + (new)read_count) элемент массива.
// В результате работы цикла read_ptr будет ссылаться уже на (SEARCHBUFFER*Downsample - 1 + read_count + (new)read_count + DATAPADDING_MSECS * (Fs / 1000) + SEARCHBUFFER * Downsample).
// Или он ссылался на 0 и заполняем 0 (DATAPADDING_MSECS * (Fs / 1000) + SEARCHBUFFER * Downsample) элементов?

fclose( Src_file );
safe_free( input_data );

sinfo-> VAD = safe_malloc( sinfo-> Nsamples * sizeof(float) / Downsample );
sinfo-> logVAD = safe_malloc( sinfo-> Nsamples * sizeof(float) / Downsample );
if( (sinfo-> VAD == NULL) || (sinfo-> logVAD == NULL))
{
*Error_Flag = 1;
*Error_Type = "Failed to allocate memory for VAD";
printf ("%s!\n", *Error_Type);
return;
}
}

Обсуждение

давно
Мастер-Эксперт
325460
1469
27.05.2021, 11:00
общий
Адресаты:
Добрый день.
попробую прокомментировать некоторые моменты.

read_ptr = sinfo-> data; // Тут получаем ссылку на 0 элемент массива в структуре. data - это массив float.
да


for( read_count = SEARCHBUFFER*Downsample; read_count > 0; read_count-- )
*(read_ptr++) = 0.0f; // Tут мы проходимся по массиву и заполняем его нулями.
// С 0 элемента массива. Количество циклов равно SEARCHBUFFER*Downsample - 1.
// В результате read_ptr ссылается на (SEARCHBUFFER*Downsample - 1) элемент массива
да


while( read_count > 0 )
{
read_count--;
*(read_ptr++) = (float)(*(p_input++)); // Тут read_ptr ссылается на (SEARCHBUFFER*Downsample - 1) элемент массива.
// В результате работы цикла read_ptr будет ссылаться уже на (SEARCHBUFFER*Downsample - 1 + read_count).
// Или он ссылался на 0 и увеличился на read_count?
}
не видно, чтобы read_ptr где-то изменялся после заполнения нулями, поэтому В результате работы цикла read_ptr будет ссылаться уже на (SEARCHBUFFER*Downsample - 1 + read_count). причем в следующем цикле чтения указатель будет еще дальше


while( read_count > 0 )
{
read_count--;
*(read_ptr++) = (float)(*(p_input++)); // Тут read_ptr ссылается на (SEARCHBUFFER*Downsample - 1 + read_count) элемент массива.
// В результате работы цикла read_ptr будет ссылаться уже на (SEARCHBUFFER*Downsample - 1 + read_count + (new)read_count).
// Или он ссылался на 0 и увеличился на read_count?
}
здесь ссылка будет зависеть от отработки предыдущего цикла чтения из файла

for( read_count = DATAPADDING_MSECS * (Fs / 1000) + SEARCHBUFFER * Downsample;
read_count > 0; read_count-- )
*(read_ptr++) = 0.0f; // Тут read_ptr ссылается на (SEARCHBUFFER*Downsample - 1 + read_count + (new)read_count) элемент массива.
// В результате работы цикла read_ptr будет ссылаться уже на (SEARCHBUFFER*Downsample - 1 + read_count + (new)read_count + DATAPADDING_MSECS * (Fs / 1000) + SEARCHBUFFER * Downsample).
// Или он ссылался на 0 и заполняем 0 (DATAPADDING_MSECS * (Fs / 1000) + SEARCHBUFFER * Downsample) элементов?
и здесь зависит от предыдущих увеличений указателя


Об авторе:
to live is to die
давно
Советник
400484
472
27.05.2021, 11:50
общий
Большое спасибо. Картина стала яснее. Понял, где не ошибся в понимании. Вполне достаточно. Спасибо.
давно
Мастер-Эксперт
325460
1469
27.05.2021, 12:03
общий
Адресаты:
обращайтесь.
многовато кода, сложно воспринять.

И я бы посоветовал использовать дебагер, чтобы отловить не правильную работу с указателями.
Об авторе:
to live is to die
давно
Советник
400484
472
27.05.2021, 12:24
общий
Цитата: CradleA
И я бы посоветовал использовать дебагер, чтобы отловить не правильную работу с указателями.

Воспользуюсь.
давно
Мастер-Эксперт
325460
1469
27.05.2021, 14:35
общий
это ответ
Пояснения по комментариям в мини-форуме ответа.

Основная не точность в том, что не совсем верна была работа с указателем на массив.

Для отладки подобных ошибок рекомендую использовать отладчик и выполнение программы в пошаговом режиме.
Об авторе:
to live is to die
Форма ответа