我想在 C 中可移植地使用 64 位有符号类型。但是 - 我知道int64_t
不能保证定义。我可以在构建系统生成中使用一些预处理器魔法(例如 CMake 的check_type_size()
)来获取预处理器定义,告诉我是否可以使用它。但是 - 我们确实有PRId64
格式说明符,我们将使用它来将int64_t
值传递给printf()
类似函数。因此,我可以使用的定义PRId64
作为确定是否int64_t
可用的代理吗?
einpoklum's questions
CMake 现在已经有一种称为“CMake 文件 API”的东西:
CMake 提供了一个基于文件的 API,客户端可以使用该 API 获取有关 CMake 生成的构建系统的语义信息。客户端可以通过将查询文件写入构建树中的特定位置来使用该 API,以请求零个或多个对象类型。当 CMake 在该构建树中生成构建系统时,它将读取查询文件并编写回复文件供客户端读取。
我不明白这个 API 应该何时使用,由谁使用。因此,我不明白,作为使用 CMake 的项目维护者,我是否需要担心这个 API 并“迎合”使用它来满足请求。我需要吗?
注意:如果答案取决于我维护哪种 CMake 项目 - 请选择几个示例(因为我在多种项目中使用 CMake)。
假设我有一个函数,它接受一些指针参数 - 一些非常量,可以通过它们写入,一些常量,只能通过它们读取。示例:
void f(int * a, int const *b);
还假设该函数不会以其他方式写入内存(即不使用全局变量,固定地址,将 const 指针重铸为非常量以及诸如此类的技巧)。
现在,是否足以(按照 C 语言标准)实现restrict
内所有读取的好处f()
,而仅restrict
输出参数?即在示例中,限制a
但不限制b
?
一个简单的测试(GodBolt)表明这种限制应该足够了。此来源:
int f(int * restrict a, int const * b) {
a[0] += b[0];
return a[0] + b[0];
}
int all_restricted(int * restrict a, int const * restrict b) {
a[0] += b[0];
return a[0] + b[0];
}
int unrestricted(int * a, int const * b) {
a[0] += b[0];
return a[0] + b[0];
}
为 x86_64 生成相同的目标代码:
f:
mov eax, DWORD PTR [rsi]
mov edx, DWORD PTR [rdi]
add edx, eax
mov DWORD PTR [rdi], edx
add eax, edx
ret
all_restricted:
mov eax, DWORD PTR [rsi]
mov edx, DWORD PTR [rdi]
add edx, eax
mov DWORD PTR [rdi], edx
add eax, edx
ret
unrestricted:
mov eax, DWORD PTR [rsi]
add eax, DWORD PTR [rdi]
mov DWORD PTR [rdi], eax
add eax, DWORD PTR [rsi]
ret
但这并非普遍的保证。
动机
数组参数可以互为别名,编译器必须小心考虑这种可能性。例如:GodBolt
int foo(int a[10], int b[10]) {
a[0] += b[0];
return a[0] + b[0];
}
int bar(int *a, int *b) {
a[0] += b[0];
return a[0] + b[0];
}
int baz(int * __restrict a, int * __restrict b) {
a[0] += b[0];
return a[0] + b[0];
}
的编译代码foo()
必须与 的类似bar()
,而不是 的类似baz()
。
问题
我想在我的函数中使用数组参数 - 甚至可能是多维数组(不是指针数组;那种用一对方括号声明并衰减为指向第一个元素的简单一级指针的数组)。我还想让编译器假定没有别名,即我想将我的数组参数标记为restrict
'ed。
我怎样才能用 C 语言做到这一点?如果我不能做到这一点 - 那是什么原因?
当将构造函数标记为已删除时,即
class MyClass {
// ...
MyClass(int x) = delete;
// ...
};
将已删除的构造函数标记为 有什么影响吗explicit
?即
explicit MyClass(int x) = delete;
?
考虑以下代码片段(改编自 cppreference.com):
constexpr std::string_view text{"Hello-+-C++-+-23-+-!"};
constexpr std::string_view delim{"-+-"};
std::ranges::for_each(text | std::views::lazy_split(delim), act_on_substring);
我想对流做同样的事情 - 比如说std::cin
- 而不是text
. 我试过了:
auto isv = std::views::istream<std::string>(std::cin);
constexpr std::string_view delim{"-+-"};
std::ranges::for_each(isv | std::views::lazy_split(delim), act_on_substring);
但这段代码无法编译:
<source>:21:31: error: invalid operands to binary expression ('basic_istream_view<basic_string<char, char_traits<char>, allocator<char>>, char, char_traits<char>>' and '_Partial<_LazySplit, decay_t<const basic_string_view<char, char_traits<char>> &>>' (aka '_Partial<std::ranges::views::_LazySplit, std::basic_string_view<char, std::char_traits<char>>>'))
21 | std::ranges::for_each(isv | std::views::lazy_split(delim), act_on_substring);
| ~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
为什么?