您好,我有 3 個問題 / 3 行代碼我不明白。如果有人可以幫助我,那就太好了。我的理解仍然不是雞蛋里的黃色。這些問題被注釋為//QUESTION:
#include <stdio.h>
#include <stdlib.h>
struct trace {
char *sign;
int *values;
struct trace *pN;
};
int main() {
int decimal[] = {4,2,1};
char text[]="Word-2!";
struct trace *pV;
pV = (struct trace*) calloc(2, sizeof(struct trace));
pV->pN = pV;
pV->values = decimal decimal[2]; // = 2
// QUESTION: explanation why decimal decimal[2] is 2 / what is decimal (not *decimal).
// My guess is: decimal[0 decimal[2]] = decimal[0 1] = decimal[1] = 2
(*pV).sign = text *decimal; // text 4 //"-2!";
*(pV 1) = pV[0]; // pV[1] = pV[0] = *pV
pV[1].values; // QUESTION: what does this do? the in front of pV instead of pV[ 1].values
*pV[1].values; // QUESTION: what does this do?
printf("%d %s\n", *pV->values, pV->sign);
printf("%d %s\n",*pV->pN[1].values, pV->pN[1].sign);
return 0;
}
編輯:這樣做的目的是找出這 2 個 printf 中顯示的內容,它們都是:“2 -2!” 和“2 -2!”
uj5u.com熱心網友回復:
您無法理解該代碼是有充分理由的;真討厭。它試圖說明指標和陣列的一些怪異行為,但它是以一種過于“棘手”且難以理解的方式完成的。它混合并匹配陣列和指標表示法,并且它訪問成員的方式不一致。它也像地獄一樣不安全。這是如何不撰寫 C 代碼的一個很好的例子。
在我們開始之前,有一個小語法備忘單:
a[i] == *(a i), therefore
a[0] == *(a 0) == *a
p->m == (*p).m == (*(p 0)).m == p[0].m
所以:
pV->values = decimal decimal[2];
TL/DR - 這是設定pV->values(與 相同(*pV).values,與 相同pV[0].values)指向decimals陣列的第二個元素;從圖形上看,它看起來像這樣:
--- --- ---
pV:| | -----> | | pV[0].sign decimal: | 4 | decimal[0]
--- --- ---
| | pV[0].values ----------> | 2 | decimal[1]
--- ---
| | pV[0].pN | 1 | decimal[2]
--- ---
| | pV[1].sign
---
| | pV[1].values
---
| | pV[1].pN
---
相當于寫
pV->values = &decimal[1];
在這種情況下,運算式 decimal“衰減”從型別“三元素陣列int”到型別“指標int”,運算式的值是陣列的第一個元素的地址(我們將了解為什么會這樣之后)。我們向這個指標值添加存盤在 中的值decimal[2],即1:
pV->values = decimal 1;
給指標加 1 會產生一個指向指向型別的下一個物件的指標,它不一定是下一個位元組;如果decimal[0]is0x8000和 an的地址int是 4 個位元組寬,那么上面加法的結果是0x8004, not 0x8001。
(*pV).sign = text *decimal;
TL/DR - 設定pV->sign為指向字串"-"的text字符;*decimal與 相同decimal[0],其中包含值4,所以上面等價于
(*pV).sign = &text[4];
到程式中的這一點,我們有以下情況:
--- --- ---
pV:| | -- --> | | pV[0].sign --- decimal: | 4 | decimal[0]
--- | --- | ---
| | | pV[0].values ------------> | 2 | decimal[1]
| --- | ---
--- | | pV[0].pN | | 1 | decimal[2]
--- | ---
| | pV[1].sign |
--- | ---
| | pV[1].values | text: |'W'| text[0]
--- | ---
| | pV[1].pN | |'o'| text[1]
--- | ---
| |'r'| text[2]
| ---
| |'d'| text[3]
| ---
----------> |'-'| text[4]
---
|'2'| text[5]
---
|'!'| text[6]
---
| 0 | text[7]
---
pV[1].values;
TL/DR - 設定pV[1].values為指向decimal[2]。
運算式 pV[1].values被決議為 (pV[1].values)- 我們將 1 添加到pV[1].values. 在程式的前面,我們復制了pV[0]to的內容pV[1],并設定pV[0].values了指向 to decimal[1]。就像我上面說的,給指標加 1 會產生一個指向下一個指向型別物件的指標;因此,pV[1].values現在指向decimal[3]。
所以現在我們的圖片是這樣的:
--- --- ---
pV:| | -- --> | | pV[0].sign --- decimal: | 4 | decimal[0]
--- | --- | ---
| | | pV[0].values ------------> | 2 | decimal[1]
| --- | ---
--- | | pV[0].pN | ------> | 1 | decimal[2]
| --- | | ---
| | | pV[1].sign --- |
| --- | | ---
| | | pV[1].values ----- text: |'W'| text[0]
| --- | ---
--- | | pV[1].pN | |'o'| text[1]
--- | ---
| |'r'| text[2]
| ---
| |'d'| text[3]
| ---
----------> |'-'| text[4]
---
|'2'| text[5]
---
|'!'| text[6]
---
| 0 | text[7]
---
*pV[1].values;
TL/DR - 我們正在增加decimal[3].
與前面的運算式類似, *pV[1].values被決議為 (*pV[1].values). 我們不是在 上加 1 ,而是在指向pV[1].values的事物上加 1 ,即。所以最后,在一切都說完之后,我們的畫面看起來是這樣的:pV[1].values decimal[3]
--- --- ---
pV:| | -- --> | | pV[0].sign --- decimal: | 4 | decimal[0]
--- | --- | ---
| | | pV[0].values ------------> | 2 | decimal[1]
| --- | ---
--- | | pV[0].pN | ------> | 2 | decimal[2]
| --- | | ---
| | | pV[1].sign --- |
| --- | | ---
| | | pV[1].values ----- text: |'W'| text[0]
| --- | ---
--- | | pV[1].pN | |'o'| text[1]
--- | ---
| |'r'| text[2]
| ---
| |'d'| text[3]
| ---
----------> |'-'| text[4]
---
|'2'| text[5]
---
|'!'| text[6]
---
| 0 | text[7]
---
那么為什么陣列運算式會“衰減”成指標運算式呢?
C 派生自早期的名為 B 的編程語言 - 在 B 中,當您宣告一個陣列時,編譯器會留出一個單獨的字來存盤陣列第一個元素的偏移量。鑒于宣告
auto a[5];
你會有這樣的記憶:
---
a: | | ----------
--- |
... |
--- |
| | a[0] <----
---
| | a[1]
---
| | a[2]
---
| | a[3]
---
| | a[4]
---
陣列下標操作a[i]定義為*(a i)- 給定存盤在 中的地址,從該地址a偏移i字并取消參考結果。
Ritchie 想將 B 的陣列行為保留在 C ( a[i] == *(a i)) 中,但他不想存盤該行為所需的單獨指標。相反,我們有這個規則:
6.3.2.1 左值、陣列和函式指示符C 2011 在線草案
...
3 除非它是運算sizeof符、運算子_Alignof或一元&運算子的運算元,或者是用于初始化陣列的字串字面量,否則為 '' 型別的運算式'' 型別的陣列被轉換為型別為 ''型別的指標的運算式,該指標指向陣列物件的初始元素,而不是左值。如果陣列物件具有暫存器存盤類,則行為未定義。
當你在 C 中宣告一個陣列時
int a[5];
你在記憶體中得到了這個:
---
a: | | a[0]
---
| | a[1]
---
| | a[2]
---
| | a[3]
---
| | a[4]
---
陣列下標操作a[i]仍定義為*(a i),但不是將指標值存盤在名為 的單獨物件中a,而是根據需要計算指標值。因此,為什么運算式decimal并text最終評估為指標值。
uj5u.com熱心網友回復:
// 問題:解釋為什么小數 小數 [2] 是 2 / 什么是小數(不是 *十進制)。
// 我的猜測是:decimal[0 decimal[2]] = decimal[0 1] = decimal 1 = 2
嚴格來說decimal decimal[2]不是2。它是指標,指向包含的記憶體2(因為簡單的decimal指向decimal[0],并添加到這個指標decimal[2],即1,給我們decimal[1],即2)。
對于接下來的兩個問題,查看運算子優先級表很有用。
pV[1].values; // it's basically (pv[1].values), i.e. incrementing of the pointer 'values'
*pV[1].values; // it's basically (*(pv[1].values)), i.e. incrementing of the integer value, pointed by the pointer 'values'
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/487153.html
下一篇:如何回傳二維陣列?
