簡體   English   中英

C編程指針

[英]C Programming Pointers

我不明白為什么最后一個代碼塊生成1819043176 1870078063 6581362 0 1 2 3 4 0 6488159 ...這些數字不是隨機的,但是為什么這些數字呢? 謝謝!

int main(void) {
    int x;
    int y[10];
    int* p;
    char* q;
    int k;
    char* prefix;

    k = 0;
    while (k < 10) {
            y[k] = k;
            k = k + 1;
    }
    x = 42;
    printf("address of y are %d %d %d\n", y, y + 1, y + 9);
    doit(y + 1);

    p = &y[0];
    printf("p is %d\n", p);
    *p = 42;
    p = p + 9;
    printf("p is %d\n", p);
    *p = 17;

    q = "hello world";
    p = "hello world";
    k = 0;
    while (k < 10) {
            printf("%d ", q[k]);
            k = k + 1;
    }
    printf("The end\n");

    k = 0;
    while (k < 10) {
            printf("%d ", p[k]);
            k = k + 1;
    }
    printf("The end\n");
}

void doit(int p[9])
{
    char* prefix = "";
    int k = 0;
    printf("p is %d at address %d\n", p, &p);
    while (k < 10)
    {
        printf("%s%d", prefix, *p);
        prefix = ", ";
        k = k + 1;
        p = p + 1;
    }
    printf("\n");
}

1819043176是十六進制的6C6C6568,將其作為字節68、65、6c,6c存儲在小字節序機器上。 這是“ hello world”的前四個字符。 等等。

通常,您不應該在C中執行這些操作,結果是不確定的或與實現有關的。

但是,如果您仍然想在內存中窺視一下,那么最好以更系統的方式進行操作,例如編寫一個小的實用程序來進行十六進制轉儲。

我沒有為您提供足夠的答案,但是我有一個重要建議: 加快編譯器的警告。 當我的bash啟動時,它將gcc別名為/usr/bin/gcc -Wall -Wextra -Werror這樣,我嘗試編譯的任何內容都必須通過GCC的最嚴格的測試(並且將所有警告均視為錯誤,因此是小錯誤)將無法編譯)。 您的代碼給了我一英里長的錯誤打印輸出(不是字面上的意思)。 一些錯誤:

  • printf()有一個特殊的指針格式說明符: %p 不要使用%d這是用於int的。
  • p是一個int * (指針到一個int ), "hello world"是一個char * 您可以將一個分配給另一個,但這通常不是一個好主意,因此,如果您確實想這樣做,則應該使用強制轉換說“嘿,我的意思是這樣做:” p = (int *) "hello world";
  • main()不返回void ,它返回一個int 您知道這一點,因為您像一個好的程序員一樣聲明了int main(void) ,但隨后我們到了main()的結尾,沒有return語句! 如果您不return任何內容,應該如何返回int 在C ++中,我們可以跳過結尾的return語句,但是在C語言中則不能(至少,我們確實不應該這樣做,因為可能會發生不好的事情)。

另外,您有一個經常重復的模式:

k = 0;
while (k < 10) {
        y[k] = k;
        k = k + 1;
}

歡迎使用for循環:

for(k = 0; k < 10; k++) {
        y[k] = k;
}

for()循環包含三個部分:

for(init; cond; inc)

init在循環之前運行一次,然后只要cond為true,循環就會執行,並在每個循環結束時執行inc 它幾乎完全等同於您正在做的事情,並且更加簡潔。

您有p指向字符串“ hello world”
但您已將p定義為指向整數的指針,因此p看起來像這樣

p[0] = 'hell'
p[1] = 'o wo'
p[2] = 'rldx'
p[3] = 'xxxx'
p[4] = 'xxxx'
p[5] = 'xxxx'
p[6] = 'xxxx'
p[7] = 'xxxx'
p[8] = 'xxxx'
p[9] = 'xxxx'

where xxxx means you have not set this memory to anything.

lets look at p[0]
h=0x68
e=0x65
l=0x6c
l=0x6c

so you have the hexidecimal number 0x6c6c6568 which you can check is 1819043176

and so on

(a)打印數字和(b)數字不是隨機的原因是因為在最后一個代碼塊中,您試圖將字符串打印為小數。 畢竟,這就是%d期望打印的內容-小數。 這與指針沒有任何關系。

您沒有說期望輸出什么,但是您必須選擇正確的格式化程序來實現。

另一個建議-在C和C ++中增加變量的通常習慣用法是

++x;

要么

x++;

將值增加1並

x += 9;

將其增加1以上(在這種情況下,顯然是9)。

我認為這是因為當格式字符串期望整數時,您正在將char傳遞給printf。 嘗試將q [k]和p [k]轉換為整數。

while (k < 10) {
        printf("%d ", (int)p[k]);
        k = k + 1;
}

對printf()的調用不是正常的函數調用,它使用varargs / stdargs,在這些函數中,該函數需要解壓縮正確的類型。

因此,輸出中的第一個數字1819043176對應於0x6C6C6568。 看看您大概希望看到的小寫字母'h'(0x68)的字符值如何是四字節整數中的最低有效字節? 這是因為varargs例程由於%d格式說明符而期望使用整數大小的參數。

這並沒有按照您的想法做(我希望,也許):

while (k < 10) {
        printf("%d ", q[k]);
        k = k + 1;
}

考慮一下q是什么,printf做什么,以及%d的含義(提示,看一下q的賦值)。 我還建議您包含期望結果的輸出,因為從代碼中您實際要完成的目標並不明顯(除了使用printf而不是int打印指向int的指針外)。

您的問題與變量p有關。 它是int *,整數變量的sizeof是4個字節(可能會因系統和編譯器而異),但是sizeof(char)是1個字節

“ hello world”字符串為12個字節-帶空值-可以3個整數定義12個字節。

在這行之后

p = "hello world";

p僅使用3 * 4內存。 (* p點數組“ y”)其余的將為null ...

暫無
暫無

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

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