Рассмотрим этот пример:
#!/usr/bin/env perl
my $vec0;
# set the first bit of vec0 to false
vec($vec0, 0, 1) = 0;
print "vec0 is " . length($vec0) . " bytes long\n";
if ($vec0) {
# what
print "vec0 is True!\n";
}
vec, используемый в оценке, кажется (почти) всегда истинным - это потому, что vec на самом деле является строкой, и поэтому $vec0 - это строка, содержащая "\0", которая не является ложной в соответствии с Perl: только строки "" и "0" " являются ложными.
(кроме того: это False, несмотря на то, что оно не равно нулю:
vec($vec0, 5, 1) = 1;
vec($vec0, 4, 1) = 1;
потому что 0x30 — это ASCII-код 0)
Хорошо: каков «правильный» способ проверки «пустого» вектора (т.е. всех битов, установленных в 0)? Подсчитать биты с помощью unpack, проверить регулярное выражение m/^\0*$/, «нормализовать» все векторы, отсекая пустые байты с конца? Кажется, это должна быть решенная проблема... и почему Perl не обрабатывает vec волшебным образом для true/false?
if ( vec($vec0, 0, 1) )?
@zdim — Все биты в векторе не установлены (0)
Знаете ли вы общее количество битов, которые вы будете использовать? например если вы знаете, что всего будет 8 бит, вы можете установить отдельные биты следующим образом: vec($vec0, 4, 1) = 1 # set bit 4 затем, чтобы проверить, установлен ли какой-либо из 8 бит, вы проверяете if (vec($vec0, 0, 8))
«Все биты в векторе не установлены (0)» — возможно, я не понимаю какую-то часть того, что вам нужно, но если вы преобразуете это в (битовую) строку с помощью my $bits = unpack("b*", $vector);, то в числовом контексте это будет равен нулю ($bits == 0), если все биты не установлены. Я не могу придумать более прямой способ, с самим вектором.
(Или с помощью $bits это легко проверить по кусочкам или по маске из такого количества нулевых битов)





Ниже приведен, вероятно, самый быстрый подход без внешнего кода C:
$vec0 !~ tr/\x01-\xFF// # True if "empty".
$vec0 =~ tr/\x01-\xFF// # True if not "empty".
Если вы используете векторы фиксированной ширины, вы можете создать еще один вектор соответствующей длины, состоящий из всех нулей, и сравнить его с теми, которые вы хотите протестировать.
my $zero_vec = pack "C*", (0) x $length_in_bytes;
# ...
if ($vec0 ne $zero_vec) {
print "vec0 is True!\n";
}
Я также нашел старый модуль на CPAN, String::BitCount, который подсчитывает количество установленных битов в строке:
use String::BitCount;
# ...
if (BitCount($vec0)) {
print "vec0 is True!\n";
}
или, может быть, регулярное выражение:
if ($vec0 !~ m/\A\x00+\z/) {
print "vec0 is True!\n";
}
pack "C*", (0) x $length_in_bytes упрощается до "\0" x $length_in_bytesЧтобы проверить это
Все биты в векторе не установлены (0).
может преобразовать его в (битовую) строку с помощью my $bits = unpack("b*", $vector), а затем в числовом контексте, который будет равен нулю ($bits == 0), если все биты не установлены. Так
if ( unpack("b*", $vec0) == 0 ) { say "All bits zero" }
Это сокращение для проверки того, что биты не установлены, ( unpack("b*", $vec0) | 0 ) == 0.
Я не думаю, что у vec есть какой-то «волшебный» способ это проверить.
Можете ли вы указать, что именно вы считаете «пустым»?