C++中使用char*的指针运算
pointer arithmetic in C++ using char*
我很难理解这两个代码片段之间的区别:
// out is of type char* of size N*D
// N, D are of type int
for (int i=0; i!=N; i++){
if (i % 1000 == 0){
std::cout << "i=" << i << std::endl;
}
for (int j=0; j!=D; j++) {
out[i*D + j] = 5;
}
}
此代码运行良好,即使对于非常大的数据集(N=100000,D=30000)也是如此。根据我对指针算术的理解,这应该会给出相同的结果:
for (int i=0; i!=N; i++){
if (i % 1000 == 0){
std::cout << "i=" << i << std::endl;
}
char* out2 = &out[i*D];
for (int j=0; j!=D; j++) {
out2[j] = 5;
}
}
然而,对于一个非常大的数据集,后者不起作用(它在索引143886处冻结-我认为它是segfault,但我不能100%确定,因为我不习惯在windows上开发),我担心我错过了指针算术如何工作的一些明显内容。这可能与推进char*有关吗?
EDIT:我们现在已经确定问题是索引溢出(即(i*D+j)>=2^32),因此使用uint64_t而不是int32_t解决了问题。我仍然不清楚的是,为什么上面的第一个案例会贯穿始终,而另一个则会出现故障。
N * D
为3e9;其不适合于32位CCD_ 2。
当使用N作为数组大小时,为什么要使用int?数组的负值有逻辑意义吗?
你说"不起作用"是什么意思?
只需将指针看作内存中的地址,而不是"对象"。
char*
void*
int*
都是指向内存地址的指针,因此在定义或传递到函数中时完全相同。
char * a;
int* b = (char*)a;
void* c = (void*)b;
a==b===c;
不同之处在于,当访问a,a[i]时,检索到的值是地址a的下一个(*a)字节大小。
当使用++来推进指针时,会推进指针设置的地址
sizeof(pointer_type) bytes.
示例:
char* a = 1;
a++;
a现在是2。
((int*)a)++;
a现在是6。
另一件事:
char* a = 10;
char* b = a + 10;
&(a[10]) == b
因为最终
a[10] == *((char*)(a + 10))
因此,您的示例中的数组大小应该没有问题,因为这两个示例是相同的。
编辑
现在请注意,没有负内存地址,因此访问具有带符号负值的数组将把该值转换为正。
int a = -5;
char* data;
data[a] == data[MAX_INT - 5]
出于这个原因,可能是(当使用符号值作为数组大小时!)您的两个示例实际上不会得到相同的结果。
版本1
for (int i=0; i!=N; i++) // i starts at 0 and increments until N. Note: If you ever skip N, it will loop forever. You should do < N or <= N instead
{
if (i % 1000 == 0) // if i is a multiple of 1000
{
std::cout << "i=" << i << std::endl; // print i
}
for (int j=0; j!=D; j++) // same as with i, only j is going to D (same problem, should be < or <=)
{
out[i*D + j] = 5; // this is a way of faking a 2D array by making a large 1D array and doing the math yourself to offset the placement
}
}
版本2
for (int i=0; i!=N; i++) // same as before
{
if (i % 1000 == 0) // same as before
{
std::cout << "i=" << i << std::endl; // same as before
}
char* out2 = &out[i*D]; // store the location of out[i*D]
for (int j=0; j!=D; j++)
{
out2[j] = 5; // set out[i*D+j] = 5;
}
}
它们正在做同样的事情,但如果out
不够大,它们都将以未定义的方式运行(并且可能崩溃)。
- 1d 智能指针不适用于语法 (*)++
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 为什么使用 "this" 指针调用派生成员函数?
- 避免指针运算,修复叮当整齐错误
- 如何在 c++ 中使用带有数学运算的引用/指针?
- 在标准布局对象中进行指针运算(例如,使用偏移量)时,我们是否需要使用 std::launder?
- 对已删除的数组进行指针运算仍然合法吗
- LLDB Python脚本中的指针运算
- C++中使用char*的指针运算
- 更正C中的指针运算
- 指针运算正在运行
- C++奇怪的指针运算
- T*与char*指针运算
- 指针运算在数组之外有用途吗?
- 我怎么知道是什么使不完整类型不完整的错误:对指向不完整类型的指针进行算术运算
- c++指针运算的怪异
- c++中auto_ptr的指针运算
- 调试断言失败!使用指针运算的字符串操作
- 限制限定符和指针运算
- std::uintptr_t可以用来避免指针越界运算的未定义行为吗?