c裡面,對於陣列a 10 而言,a是其首元素的記憶體位址,那麼a是乙個指標變數嗎?或是指標常量嗎?

時間 2021-05-30 00:07:26

1樓:

開始你可能看不懂,不必深究,這個得慢慢去體會,用的多了沒準哪天就開竅了。如果有問題再說。

2樓:XYZ指示物

一般人會想用typeid(expr).name() 比如typeid((a)).name()

有些人可能會想到用decltype+模板然後自己輸出這樣就能不丟失&和&&和CV之類的資訊

然而我研究上述方法後得出了乙個終極大招template

T>struct

type_dumper

;使用方法 type_dumper dump; 比如 type_dumper dump;

編譯然後你就會得到診斷資訊類似如下error: static_assert failed "type dump"

note: in instantiation of template class 'type_dumper' requested here

於是乎你就精確地得知了乙個表示式的型別當然type_dumper的實現無論反正報錯就好了

3樓:李鵬

試著來回答一下這個問題,如有錯誤,一定要幫我指出來哈。

先說結論,C語言裡,陣列名是「不可修改的左值」。

在C語言裡,變數有左值和右值之分。

比如 x = y;中,x為左值,y為右值。區別如下:

x代表乙個記憶體位址,y代表的是某個記憶體位址中存放的內容。

x在編譯時已知,y在執行時才可知。

不過,陣列名卻是另類的存在。

陣列名代表的是內容還是位址?是位址。所以陣列名是左值。

陣列名可以被修改被賦值嗎?不可以。而左值是可以的。這跟左值矛盾。

為此,在新的ANSI C標準中,x已不再稱作左值,而稱作「可修改的左值」。

「可修改」意味著它可以被賦值。

而陣列名是「不可修改的左值」,它不能被賦值。

那麼,陣列名是指標常量還是指標變數?都不是。它只是有點像指標常量而已。

在C裡,指標和陣列給人一種錯覺,認為它們是相同的。其實完全不同。

比如:int a[10];

int *p;

陣列名a裡存放了乙個位址,這個位址的內容是乙個int型整數。

指標p也存放了乙個位址,這個位址的內容是另外乙個位址(一般是乙個long型整數)。

4樓:wcy123

#include

#include

#include

void

foo(

const

char

*file

,int

line

,const

char*s

,void*p

)#define FOO(x) foo(__FILE__,__LINE__,#x,((void*)(x)))

intmain

(int

argc

,char

*argv

)程式輸出結果

gcc -O3 junk.c && ./a.out

junk.c:13 0x7fff846d9040 junk

junk.c:14 0x7fff846d9040 &junk

junk.c:14 0x7fff846d9040 junk[0]

junk.c:15 0x7fff846d9040 &junk[0]

junk.c:16 0x7fff846d9040 &junk[0][0]

可以看到,這五個東西都是同樣的值。

在組合語言看來,這五個東西沒有區別。

C 語言中陣列的概念是乙個十分醜陋的設計。我寧願把它看作是語法糖。

就是說,用這種語法,可以方便的描述一連串記憶體的值,也方便計算元素位址的偏移量。

但無論如何,他就是一塊連續的記憶體。

記得很早以前我面試的時候,有人問我 C 語言裡面指標和陣列有啥區別,我腦子裡面想的是彙編,脫口說,沒有區別。從面試官鄙夷的表情上看到,我明顯回答錯了。我臨場反應慢,沒有想到怎麼解釋這個就是乙個語法糖,本質上沒有區別。

何為本質,看機器語言。

0000000000400410 :

400410: 48 83 ec 68sub $0x68,%rsp

400414: 41 b8 51 06 40 00 mov $0x400651,%r8d

40041a: ba 0d 00 00 00 mov $0xd,%edx

40041f: 48 89 e1mov %rsp,%rcx

400422: be 56 06 40 00 mov $0x400656,%esi

400427: bf 44 06 40 00 mov $0x400644,%edi

40042c: 31 c0xor %eax,%eax

40042e: e8 ad ff ff ff callq 4003e0

400433: 48 89 e1mov %rsp,%rcx

400436: 41 b8 5e 06 40 00 mov $0x40065e,%r8d

40043c: ba 0e 00 00 00 mov $0xe,%edx

400441: be 56 06 40 00 mov $0x400656,%esi

400446: bf 44 06 40 00 mov $0x400644,%edi

40044b: 31 c0xor %eax,%eax

40044d: e8 8e ff ff ff callq 4003e0

400452: 48 89 e1mov %rsp,%rcx

400455: 41 b8 5d 06 40 00 mov $0x40065d,%r8d

40045b: ba 0f 00 00 00 mov $0xf,%edx

400460: be 56 06 40 00 mov $0x400656,%esi

400465: bf 44 06 40 00 mov $0x400644,%edi

40046a: 31 c0xor %eax,%eax

40046c: e8 6f ff ff ff callq 4003e0

400471: 48 89 e1mov %rsp,%rcx

400474: 41 b8 66 06 40 00 mov $0x400666,%r8d

40047a: ba 10 00 00 00 mov $0x10,%edx

40047f: be 56 06 40 00 mov $0x400656,%esi

400484: bf 44 06 40 00 mov $0x400644,%edi

400489: 31 c0xor %eax,%eax

40048b: e8 50 ff ff ff callq 4003e0

400490: 31 c0xor %eax,%eax

400492: 48 83 c4 68add $0x68,%rsp

400496: c3retq

可以看到,每次呼叫 printf 之前,都是 "mov %rsp, %rcx" ,"%rsp" 就是這五個東西,

儘管語法亂七八糟,編譯出來的都是 "%rsp"

註解linux ABI $rcx 是第四個引數

因為用了 -O3 優化,foo 被 inline 展開了。

mov $0x400644 %rdi 是第乙個引數,"%s:%d %p %s" 這個常量字串。可以看到常量儲存的位置。

mov $0x400656, %esi 是第二個引數 "junk.c" 字串常量,可以看到同名常量字串有的時候會被合併。

mov $0xf, %edx 是第三個引數, line

開頭的 sub $0x68,%rsp 表示申請內存在 stack 上。3x4x8 = 0x60 ,怎麼多出來乙個 long long? 這個我搞不懂

5樓:啊魚

為什麼非要把陣列說成指標,

雖然陣列和指標有些不倫不類的關係,但是,

為什麼非要把陣列說成指標,

陣列就陣列,指標就指標,多好,

只不過是陣列名有時可以當成首位址使用,

為什麼非要把陣列說成指標,

C 中如何建立乙個不定長陣列的陣列指標?

按照 C 的寫法應該是 int p 4 但是既然是用 C 最好的方法還是用模板容器 using arr type std vector array 4 arr typep1 arr typep2 arr typep3 arr typep4 arr typep5 然後想要拷貝 std vector p...

為什麼c 中陣列不能直接拷貝給另一陣列?

d41d8c 結構體的拷貝建構函式中,陣列可以拷貝。lambda的拷貝捕獲可以捕獲陣列 int a 2 a structured binding也可以產生陣列的拷貝 int a 2 auto x,y a 中,x和y繫結到a的副本中的元素。甚至char a asdf 這種初始化也可以看作陣列拷貝的特例...

c 定義全域性陣列,當陣列很大時,位址是不連續的嗎

不對,C 中定義的陣列,在記憶體分配上都是分配一塊連續的記憶體來儲存的,這個是不用懷疑的。問題分析 C 中,陣列在記憶體中的分配有靜態分配和動態分配兩種。靜態陣列建立的方式為 A a,它在棧上分配空間 動態陣列建立的方式是使用new 或 malloc在堆上分配。靜態分配 intarr 10 inta...