[英]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上-我認為它是段錯誤的,但是我不確定100%,因為我不習慣在Windows上進行開發),恐怕我缺少有關指針算法工作原理的明顯信息。 可能與推進char *有關嗎?
編輯:我們現在已經確定問題是索引溢出(即(i * D + j)> = 2 ^ 32),因此使用uint64_t而不是int32_t可以解決此問題。 對我來說,仍然不清楚的是,為什么上述第一個案件會同時發生,而另一個則是段錯誤。
N * D
為3e9; 不適用於32位int
。
當使用N作為數組的大小時,為什么要使用int? 數組的負值是否具有邏輯含義?
你是什么意思“不工作”?
只是將指針視為內存中的地址,而不是“對象”。
char*
void*
int*
是所有指向內存地址的指針,因此在定義或傳遞給函數時完全相同。
char * a;
int* b = (char*)a;
void* c = (void*)b;
a == b == c;
區別在於訪問a,a [i]時,檢索到的值是地址a中的下一個sizeof(* a)字節。
當使用++前進指針時,指針所設置的地址通過
sizeof(pointer_type) bytes.
例:
char* a = 1;
a++;
現在是2。
((int*)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
不夠大,它們都將以不確定的方式運行(並可能崩潰)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.