Существует серьезное заблуждение и некоторые другие проблемы:
memset()
не изменяется padded
То есть переменная в вашей функции не изменяется; memset()
просто устанавливает данные, на которые указывает padded
.
Предполагаемая операция сброса padded -= ssize + 1
, следовательно, вызывает неопределенное поведение, обращаясь к памяти, которую вы не выделяли.
Использование:
strcpy(padded + bits - ssize, string);
вместо двух строк:
padded -= ssize + 1;
strncpy(padded, string, ssize);
Использование strcpy()
безопасно, потому что вы знаете все размеры.
Обратите внимание, что malloc()
не возвращает инициализированные данные, вы не можете гарантировать, что последний выделенный байт будет нулевым. Для этого вам придется использовать calloc()
.
Обратите внимание, что операция memset()
НЕ обнуляет вашу строку.
Обратите внимание, что использование strncpy()
, как это ни парадоксально, также не гарантирует нулевое завершение и действительно не завершает нулевую строку, даже если вы правильно указали начальную позицию. Напротив, использование strcpy()
гарантирует нулевое завершение.
Рабочий код
Обратите внимание на пересмотренный интерфейс - используйте const char *
для первого аргумента. (static
просто получает код для компиляции под моими флагами компиляции по умолчанию без жалобы на отсутствие предварительного объявления функции. Конечно, вы не будете использовать это для библиотечной функции, объявленной в заголовке.)
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static char *strpadleft(const char * string, char pad, size_t bytes)
{
size_t ssize = strlen(string);
size_t bits = bytes * 8;
char *padded = (char *) malloc(bits + 1);
assert(ssize < bits);
memset(padded, pad, bits - ssize);
strcpy(padded + bits - ssize, string);
return padded;
}
int main(void)
{
const char *data = "0100100001";
char *pad = strpadleft(data, '0', 4);
printf("Data: <<%s>> padded <<%s>> (%d)\n", data, pad, (int)strlen(pad));
free(pad);
return(0);
}
Комментарий
Вам действительно нужно решить, какое поведение будет подходящим, если ssize > bits
(подсказка: assert()
неверна). Скорее всего, вы просто дублируете исходную строку. Примечание: абсолютно НЕ будет приемлемо для возврата указателя на исходную строку. Функция возвращает указатель на строку, которая должна быть освобождена приложением; поэтому вы всегда должны возвращать выделенную строку. В противном случае ваша функция станет непригодной для использования; код должен проверить, совпадает ли возвращаемое значение с аргументом, и не освобождать возвращаемое значение, если оно совпадает. Тьфу!
Квазификсированный код
Демонстрация отсутствия нулевого завершения в исходном коде:
static char * strpadleft(const char * string, char pad, size_t bytes)
{
size_t ssize = strlen(string);
size_t bits = bytes * 8;
char *padded = (char *) malloc(bits + 1);
padded[bits] = 'X'; // Overwrite last allocated byte
memset(padded, pad, bits);
strncpy(padded + bits - ssize, string, ssize);
return padded;
}
С той же тестовой программой, что и раньше, и полагаясь на неопределенное поведение (не было никакой гарантии, что байт после X будет нулевым), я получил:
Data: <<0100100001>> padded <<00000000000000000000000100100001X>> (33)
Обратите внимание, что 'X' не был перезаписан strncpy()
! Вы можете исправить это с помощью ssize + 1
, но почему бы просто не использовать strcpy()
... как уже было сказано ...