我不太熟悉C标准,所以请耐心等待.
我想知道,按标准保证memcpy(0,0,0)是否安全.
我能找到的唯一限制是,如果内存区域重叠,那么行为是未定义的......
但我们可以认为这里的内存区域重叠吗?
这个问题的动机是我在C/C++中实现加密算法(例如SHA-1),编写可移植平台无关的代码,并彻底避免未定义的行为.
假设标准化的加密算法要求您实现此目的:
b = (a << 31) & 0xFFFFFFFF
Run Code Online (Sandbox Code Playgroud)
where a和b是无符号的32位整数.请注意,在结果中,我们丢弃高于最低32位的任何位.
作为第一个天真的近似,我们可以假设int在大多数平台上都是32位宽,所以我们写:
unsigned int a = (...);
unsigned int b = a << 31;
Run Code Online (Sandbox Code Playgroud)
我们知道这个代码无处不在,因为int在某些系统上是16位宽,在其他系统上是64位,甚至可能是36位.但是使用stdint.h,我们可以使用以下uint32_t类型改进此代码:
uint32_t a = (...);
uint32_t b = a << 31;
Run Code Online (Sandbox Code Playgroud)
所以我们完成了,对吧?这就是我多年来的想法.... 不完全的.假设在某个平台上,我们有:
// stdint.h
typedef unsigned short uint32_t;
Run Code Online (Sandbox Code Playgroud)
在C/C++中执行算术运算的规则是,如果类型(例如short)比类型更窄int,那么int如果所有值都适合,则它会变宽,unsigned int否则.
假设编译器定义short为32位(带符号)和int48位(带符号).然后这些代码行:
uint32_t a = (...);
uint32_t b = a << …Run Code Online (Sandbox Code Playgroud) 以下两行有什么区别?
map<int, float> map_data;
map<const int, float> map_data;
Run Code Online (Sandbox Code Playgroud) 比较悬空指针是否合法?
int *p, *q;
{
int a;
p = &a;
}
{
int b;
q = &b;
}
std::cout << (p == q) << '\n';
Run Code Online (Sandbox Code Playgroud)
注意如何既p与q点有对象已经消失了.这合法吗?
请考虑以下示例:
#include <cstdlib>
int main() {
const int m = 42;
[] { m; }(); // OK
const int n = std::rand();
[] { n; }(); // error: 'n' is not captured
}
Run Code Online (Sandbox Code Playgroud)
为什么我需要捕获n第二个lambda而不是m第一个lambda?我在C++ 14标准中检查了第5.1.2节(Lambda表达式)但我无法找到原因.你能指点我解释一个段落吗?
更新:我在GCC 6.3.1和7(主干)中观察到了这种行为.Clang 4.0和5(主干)在两种情况下都失败并出错(variable 'm' cannot be implicitly captured in a lambda with no capture-default specified).
这段代码在 C++20(使用 gcc 10.1)中编译,typename在依赖类型之前没有使用关键字std::vector<T>::iterator。为什么要编译?
#include <vector>
template<typename T>
std::vector<T>::iterator // Why does this not require "typename" before it?
f() { return {}; }
int main() {
auto fptr = &f<int>;
}
Run Code Online (Sandbox Code Playgroud)
在对这个最近问题的评论中出现了一个有趣的讨论:现在,虽然那里的语言是C,但讨论已经转向C++标准所指定的内容,即使用 a 访问多维数组的元素时构成未定义行为的内容。功能类似于std::memcpy.
首先,这是该问题的代码,已转换为 C++ 并const尽可能使用:
#include <iostream>\n#include <cstring>\n\nvoid print(const int arr[][3], int n)\n{\n for (int r = 0; r < 3; ++r) {\n for (int c = 0; c < n; ++c) {\n std::cout << arr[r][c] << " ";\n }\n std::cout << std::endl;\n }\n}\n\nint main()\n{\n const int arr[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };\n int arr_copy[3][3];\n print(arr, 3);\n std::memcpy(arr_copy, arr, sizeof arr);\n …Run Code Online (Sandbox Code Playgroud) c c++ multidimensional-array undefined-behavior language-lawyer
我已经检查了所有主要的编译器,sizeof(std::tuple<int, char, int, char>)所有这些都是16。大概它们只是将元素按顺序放入元组,因此由于对齐而浪费了一些空间。
如果元组在内部像这样存储元素:int, int, char, char,则其sizeof可能为12。
实现有可能执行此操作,还是该标准中的某些规则禁止这样做?
根据 C11 标准的 \xc2\xa76.3.2.3 \xc2\xb63,C 中的空指针常量可以由实现定义为整数常量表达式0或转换为 的此类表达式void *。在 C 语言中,空指针常量由宏定义NULL。
我的实现(GCC 9.4.0)NULL通过stddef.h以下方式定义:
#define NULL ((void *)0)\n#define NULL 0\nRun Code Online (Sandbox Code Playgroud)\n为什么上述两个表达式在 的上下文中被认为在语义上等效NULL?更具体地说,为什么存在两种而不是一种表达同一概念的方式?