簡體   English   中英

與C中的指針混淆了

[英]Got confused with pointers in C

我剛剛在我的教科書中找到指針,但它解釋得不夠好,所以我需要一些幫助。

我知道什么是指針,他們做了什么。 例如,我非常了解以下示例:

#include <stdio.h>

int main ()
{
    int num = 5;
    int *point;

    point = &num;

    *point = 8;

    printf("%d %d", num, *point);

    return 0;
}

point指向num(將num的地址存儲為其值)。 然后我解除引用點來改變num的原始值。

現在考慮相同示例的明顯修改版本:

#include <stdio.h>

int main ()
{
    int num = 5;
    int *point;

    point = 8;

    printf("point: %d\n", point);

    printf("sum (%d) = num (%d)+ point (%d)", num+point, num, point);

    return 0;
}

我有一些問題:

1-為什么甚至可以為指針(點)分配正常值(8)? 是不應該只將地址存儲到其他東西的指針? 第8行發生了什么?

2- i編譯了代碼,對於第二個printf,它顯示:sum(28)= num(5)+ point(8)為什么sum等於28? 5 + 8是13.發生了什么?

你可以點point ,在內存地址8(或0x00000008)。 它相當於point = (int*)8; 我得到一個友好的<Unable to read memory>錯誤,因為我正在使用c ++,我認為它保護我免受我的愚蠢。

為什么5 + 8 = 28? 如果向類型為T的指針添加數字n,則將此指針移動到類型為T的n個元素。您的機器正在處理32位整數,大小為4字節,因此8 +(5 * 4)= 28 。

在第二個示例中,您為指針指定了8。 我希望你的編譯器得到一個很好的警告。 但你可以分配8.只是不要取消引用它。 您可能會遇到分段錯誤或更糟。 num + point的總和非常有意義。 它叫做指針算術。 point是指向整數的指針。 你機器上的int是4個字節。 num + point的總和是(5 * sizeof(int))+ 8,在您的系統上是28。

因為幾乎所有C編譯器都將指針實現為整數以支持指針算術。

int arr[10];
int *ip = arr;

arr[2] = 42;      // this is equivalent to:
*(ip + 2) = 42;   // or
*(2 + ip) = 42;

假設, &arr[0] (整數數組arr的第一個元素的地址)是0xcafe0000 假設一個int值占用內存中的4個字節。 然后&arr[1]位於0xcafe0004&arr[2]位於0xcafe0008 ,依此類推,增量為4字節。

編譯器看到了這個:

int i = arr[5];       // which is equivalent to:
int j = *(arr + 5);

並取地址0xcafee0000 ,並添加(5 * sizeof(int)) ,在解除引用之前將其輸出到0xcafee0028

這就是為什么當你向指針類型轉換任何ol'整數時,請說:

int *p = (int*) 8;

然后添加它:

p = p + 5;    // p := 28

編譯器將獲取p的值,並將其添加到操作數的5 int的大小

指針是一個數字,就像int是一個數字一樣。 為指針分配硬編碼值是合法的,但會發出警告

point = 8;

但除非你正在使用嵌入式系統並知道該地址是什么,否則無意義8。

盡管您的程序在內存訪問限制中幸存,但您不知道內存地址8的值是什么。因此您無法理解計算結果。 這是未定義的行為,因為程序沒有在該地址設置值。

1 - 為什么甚至可以為指針(點)分配正常值(8)? 是不應該只將地址存儲到其他東西的指針? 第8行發生了什么?

指針存儲內存地址是正確的,但這個內存地址只記錄一個數字。 通常,指針的值要大得多,但沒有什么可以阻止你為指針分配內存地址(8)。 不要指望使用這個地址。 通常使用的一種方法是使用NULL指針

int *point = NULL;

是相同的

int *point = 0;

2- i編譯了代碼,對於第二個printf,它顯示:sum(28)= num(5)+ point(8)為什么sum等於28? 5 + 8是13.發生了什么?

指針算法不像你最初期望的那樣工作,並且存儲內存位置,指針也有一個內存類型:

int *point;

在這種情況下, point知道它指向一個int 因此,當一個遞增的指針不會將它的位置增加一個字節時,它會增加sizeof(int) ,在你的情況下是4個字節。 這意味着point++point = point + 1會將指針移動到它認為當前指向的東西的任何大小,這樣做的原因是可以輕松地沿着對象的數組或內存塊移動相同的類型。

要了解這個概念,請嘗試使用這一塊代碼

#include <stdio.h>

int main()
{
    int x;
    int * ptr = &x;

    for(int i = 0; i < 5; i++)
    {
        printf("pointer address: %p\n", ptr + i);
    }
return 0;
}

具體來說,嘗試將xptr的類型從int更改為charlong long並查看它所產生的差異!

問題是計算機指針只是具有特殊含義的整數值,即內存地址值。 因此,總是可以將整數值賦給指針,盡管最終可能會得到一個空指針。

num +指針為28的原因是因為您的計算機是因為您正在使用的計算機中的地址是32位。 因此C具有稱為指針算法的這一特性,這意味着向指針添加/減去任何值實際上會增加4 * num,因為機器具有的每個32位字中有4個字節。 結果你得到了點+ num == 8 +(4 * 5)。

===編輯

同樣,當你在C中進行指針運算時,機器實際上會向指針添加數據類型的字節數。 例如,如果您聲明:

int num = 5;
char * point;

然后當你這樣做

point = 8;

point + num == 8 + 5 == 13的結果,因為在大多數C實現中,char是單個字節。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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