簡體   English   中英

使用char *的C ++中的指針算術

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM