short int这是关于在“常规算术转换”期间提升 s时的正确诊断。在操作期间,/可以合理地发出诊断信息,但在操作期间/=不应发出任何诊断信息。
gcc-trunk 和 clang-trunk 的行为似乎没问题(都不发出下面第一种或第二种情况的诊断信息)...直到...
我们添加了完全不相关的-fsanitize=undefined...之后,完全奇怪的是:
gcc-trunk 会针对这两种情况发出诊断信息。至少对于第二种情况确实不应该。
这是 gcc 中的错误吗?
int main() {
short sum = 50;
short count = 10;
// sum and count get promoted to int for the "usual arithmetic conversions"
// then the assignment could result in a reasonable -Wconversion diagnostic for reduction back
// to short
// However clang-trunk and gcc-trunk choose NOT TO issue a diagnostic …Run Code Online (Sandbox Code Playgroud) 我得到了
Error C2678 binary '*': no operator found which takes a left-hand operand of type 'const _InIt' (or there is no acceptable conversion)
Run Code Online (Sandbox Code Playgroud)
它是由 MSVC (2022, V17.1) 标头中的代码抛出的<algorithm>。
Error C2678 binary '*': no operator found which takes a left-hand operand of type 'const _InIt' (or there is no acceptable conversion)
Run Code Online (Sandbox Code Playgroud)
const由于上面一行的原因,第二行抛出了错误。
我传入的迭代器是“平面文件”上的自定义 LegacyRandomAccessIterator,它operator*看起来像这样:
template <class _FwdIt, class _Ty, class _Pr>
_NODISCARD _CONSTEXPR20 _FwdIt lower_bound(_FwdIt _First, const _FwdIt _Last, const _Ty& _Val, _Pr _Pred) {
... …Run Code Online (Sandbox Code Playgroud) 我可以使用 astd::array<int, N>来为 a 的部分别名int[]而不调用 UB 吗?
https://en.cppreference.com/w/cpp/container/array “此容器是一个聚合类型,其语义与将 C 样式数组 T[N] 作为其唯一非静态数据成员的结构体具有相同的语义。 ”
动机:copy下面的函数不受我的控制,需要通过引用进行单个分配。只有 a struct { int[N]; }like astd::array<int, N>才能进行那种“多对象赋值”?
这是UB吗?
还有别的办法吗?
#include <iostream>
#include <array>
template <std::size_t N>
void print(int (&arr)[N], std::size_t number_rows, std::size_t number_cols) {
assert(number_rows * number_cols == N);
for (std::size_t r = 0; r != number_rows; ++r) {
for (std::size_t c = 0; c != number_cols; ++c) {
std::cout << arr[r * number_cols + c] …Run Code Online (Sandbox Code Playgroud) 在 C 中实现处理一系列类型的泛型函数时,void*经常使用。该libc函数qsort()是一个经典的例子。在内部qsort()和许多其他算法中都需要一个swap()函数。
通用交换的一个简单但典型的实现如下所示:
void swap(void* x, void* y, size_t size) {
char t[size];
memcpy(t, x, size);
memcpy(x, y, size);
memcpy(y, t, size);
}
Run Code Online (Sandbox Code Playgroud)
对于较大的类型,可以使用逐字节交换,否则malloc会很慢,但这里的重点是当这个泛型swap()用于小类型时会发生什么。
事实证明,如果我们匹配一些常见的类型大小(x86_64 上的 4 和 8 字节的 int 和 long),还包括浮点、双精度、指针等,我们可以获得令人惊讶的性能提升:
void swap(void* x, void* y, size_t size) {
if (size == sizeof(int)) {
int t = *((int*)x);
*((int*)x) = *((int*)y);
*((int*)y) = t;
} else if (size == sizeof(long)) { …Run Code Online (Sandbox Code Playgroud) 混合有符号和无符号算术的典型示例似乎是:
\n unsigned int u = 10;\n int a = -42;\n auto tmp1 = u - a;\n std::cout << tmp1 << std::endl;\n int tmp2 = tmp1;\n std::cout << tmp2 << std::endl;\nRun Code Online (Sandbox Code Playgroud)\n(请注意,我使用的是auto tmp1这样我可以显示中间结果并检查类型。当然,在实际代码中,这都是一行)
如果你启用足够多的警告(-Wconversion在 clang-13 上,另外,-Wsign-conversion在 gcc-11 上),编译器会很好地抱怨:
main.cpp:148:21: warning: conversion to \xe2\x80\x98unsigned int\xe2\x80\x99 from \xe2\x80\x98int\xe2\x80\x99 may change the sign of the result [-Wsign-conversion]\n 148 | auto tmp1 = u - a;\n | ^\nmain.cpp:150:16: warning: conversion to \xe2\x80\x98int\xe2\x80\x99 from \xe2\x80\x98unsigned int\xe2\x80\x99 …Run Code Online (Sandbox Code Playgroud) 外部 API 需要一个指向值数组(此处为 int 作为简单示例)的指针加上一个大小。
以 4 为一组处理元素在逻辑上更清晰。
因此,通过“4 组”结构处理元素,然后使用指针转换将这些结构的数组传递到外部 API。请参阅下面的代码。
蜘蛛感知说:=> 可能的 UB 中存在“严格混叠违规” reinterpret_cast?
以下内容static_asserts是否足以确保:a) 这在实践中有效 b) 这实际上符合标准而不是 UB?
否则,我需要做什么,才能使其“不是UB”。工会?请问具体怎么样?
或者,是否有一种不同的、更好的方法?
#include <cstddef>
void f(int*, std::size_t) {
// external implementation
// process array
}
int main() {
static constexpr std::size_t group_size = 4;
static constexpr std::size_t number_groups = 10;
static constexpr std::size_t total_number = group_size * number_groups;
static_assert(total_number % group_size == 0);
int vals[total_number]{};
struct quad {
int val[group_size]{};
};
quad vals2[number_groups]{};
// deal with …Run Code Online (Sandbox Code Playgroud) 为什么 C++ 选择原始类型重载匹配而不是“更好”的匹配初始值设定项列表?
#include <vector>
void foo([[maybe_unused]] int i) {}
void foo([[maybe_unused]] const std::vector<int>& v) {}
int main() {
foo(0);
foo({1,2,3});
foo({0}); // calls foo(int) and issues a warning,
// rather than what seems like the "better"
// match foo(vector).. why?
}
Run Code Online (Sandbox Code Playgroud)
<source>:10:9: warning: braces around scalar initializer [-Wbraced-scalar-init]
foo({0}); // calls foo(int) and issues a warning,
^~~
Run Code Online (Sandbox Code Playgroud)
也许是“令人惊讶”的结果,因为编译器选择了随后发出诊断的选项?
使用 Clang 14
c++ overloading initializer-list language-lawyer overload-resolution