pub struct HashMap<K, V> {
table: Table<(K, V)>,
}
struct Table<T> {
// битовая маска занятых ячеек в items
mask: u64,
items: Box<[std::mem::MaybeUninit<Item<T>>; 64]>,
len: usize,
}
struct Item<T> {
data: T,
next: Option<std::ptr::NonNull<Item<T>>>,
}
pub enum Entry<'a, K, V> {
Vacant(VacantEntry<'a, K, V>),
Occupied(OccupiedEntry<'a, K, V>),
}
pub struct VacantEntry<'a, K, V> {
hash: u64,
key: K,
table: &'a mut Table<(K, V)>,
}
pub struct OccupiedEntry<'a, K, V> {
elem: Bucket<(K, V)>,
table: &'a mut Table<(K, V)>,
}
// указатель на Item.data
struct Bucket<T> {
ptr: std::ptr::NonNull<T>,
}
impl<K, V> HashMap<K, V> {
pub fn entry<'a>(&'a mut self, key: K) -> Entry<'a, K, V>
where
K: Eq + std::hash::Hash,
{
use std::hash::Hasher as _;
let mut hasher = self.get_hasher();
key.hash(&mut hasher);
let hash = hasher.finish();
if let Some(elem) = self.table.find(hash, |(k, _)| key == *k) {
Entry::Occupied(OccupiedEntry {
elem,
table: &mut self.table,
})
} else {
Entry::Vacant(VacantEntry {
hash,
key,
table: &mut self.table,
})
}
}
fn get_hasher(&self) -> impl std::hash::Hasher {
todo!()
}
}
impl<T> Table<T> {
fn find(&self, hash: u64, is_match: impl FnMut(&T) -> bool) -> Option<Bucket<T>> {
todo!()
}
}
можно подумать, что при объявлении указателя, символ * относится к имени(не как часть, а как что-то зависящее от него), а не к типу.
const char *a, b;
можно превратить в const char (*a), b
, но нельзя превратить в const (char *a), b
или в char (const *a), b
.I'm still uncertain about the language declaration syntax, where in declarations, syntax is used that mimics the use of the variables being declared. It is one of the things that draws strong criticism, but it has a certain logic to it.
struct OpaqueAddress;
using Address = OpaqueAddress*;
using Address = uint32_t;
enum class Address : uintptr_t { NUL = 0 };
intptr_t
и uintptr_t
[?], а еще ptrdiff_t
[?].enum class MemoryAddress : uintptr_t;
. Пустое перечисление с достаточной шириной и выравниванием избавит от возможности случайно что-то куда-то прибавить или умножить, да и от неявных преобразований убережет. А перегрузка операторов поможет разрешить только определенные операции.У меня имеется список исходных файлов и список файлов в которые они должны быть скомпилированы.
SRCS = ./a/prog1.c ./a/b/prog2.c ./a/b/c/prog3.c
OUTS = ./outs/prog1.out ./outs/prog2.out ./outs/prog3.out
.PHONY: all
SRCS = ./a/prog1.c ./a/b/prog2.c ./a/b/c/prog3.c
OUTS = ./outs/prog1.out ./outs/prog2.out ./outs/prog3.out
all: $(OUTS)
define make_rule =
$(firstword $(1)): $(firstword $(2))
@echo compile $$< to $$@
gcc $$< -o $$@
$(if $(wordlist 2,$(words $(1)),$(1)),
$(eval $(call make_rule,
$(wordlist 2,$(words $(1)),$(1)),
$(wordlist 2,$(words $(2)),$(2)))))
endef
$(eval $(call make_rule,$(OUTS),$(SRCS)))
Я встречал информацию, что в России величина девиации 75 кГц в нижнюю и 75 кГц в верхнюю.Верно для полосы частот 87,5—108 МГц.
При максимальной амплитуде звукового сигнала, частота модулированного сигнала максимальна: 102.375 МГц, а при минимальной амплитуде звукового сигнала, частота модулированного сигнала минимальна: 102.225 МГц.Неверно. Модулирующий сигнал имеет частоты до 15 кГц. А 75 кГц нужно для стерео-сигнала, для RDS и чтобы оставить запас до частот соседней радиостанции (вы же не хотели бы включить одну радиостанцию и слышать вместе с ней отголоски другой радиостанции).