2 回答

TA貢獻1850條經(jīng)驗 獲得超11個贊
這問題其實挺有趣的,對于argv來說,既然定義成
char *argv[]
那不就是說明argv是一個指向字符串的指針數(shù)組,怎么也能左值操作?
我們知道數(shù)組名其實就是一個常量,是不能被直接修改的,這是它與指針一個最大的區(qū)別。
這里argv與arr最大的區(qū)別是一個是函數(shù)中的參數(shù),一個是定義的局部變量。
一般可以從兩個方面來理解這個問題。
一個方面,正如藍皮鼠所說的,main函數(shù)的原型中argv其實是
char **argv
這樣,對于定義成char * argv[]的參數(shù),gcc在編譯時會有一個隱式轉(zhuǎn)換,因為這里這兩者是是相容的,就算你定義成
char const * argv[]
對于argv來說,這個定義就不相容了。不過一般會有兩個結(jié)果,要么編譯器很嚴格直接報錯,要么會給個警告信息,然后繼續(xù)把它當成 char **argv 來用。
所以你直接對argv進行左值運行,代碼可以被編譯通過,就正常了。
另一方面,在C語言中,參數(shù)中的數(shù)組傳遞有些特殊。比如下面的代碼:
#include <stdio.h>int func(char *v[]){ *++v; printf("&v=%x\t v=%x\n",&v,v); }int main(int argc, char const* argv[]){ char const* arr[]={"1","2","3"}; printf("&argv=%x\t argv=%x\n",&argv,argv); printf("&argc=%x\t argc=%x\n",&argc,argc); func(argv); }
因為main函數(shù)是程序的入口函數(shù),是被編譯內(nèi)部定義好的,所以可以再定義一個
int func(char *v[])
結(jié)果發(fā)現(xiàn)這個v仍然可以進行左值操作。
上面說了參數(shù)中數(shù)組的傳遞有些特殊,因為在實際處理參數(shù)中的數(shù)組時,其實編譯器是把它當成一個指針來處理。
比如你定義好一個數(shù)組
`
char arr2[10];`
假定有一個函數(shù),其原型如下:
int func2(char p[]);
那么當以下調(diào)用發(fā)生時:
func2(arr2);
arr2的值會被復制一份到一個內(nèi)部局部變量指針(堆?;蚣拇嫫?中,這個指針指向arr2[0]的位置。這樣arr就被傳遞進func2函數(shù)中了。
同時,這也是在定義函數(shù)的參數(shù)時,如果參數(shù)中有數(shù)組,我們一般不用在數(shù)組標記中間寫上數(shù)組長度值的原因,因為沒有意義,實際只是把數(shù)組的地址進行了傳遞。
比如:
'int func2(char arr[10])'
這就是我的理解和說明,希望對你有所幫助。

TA貢獻1840條經(jīng)驗 獲得超5個贊
我覺得是這樣的
char const* arr[]={"Hello","World","AndyXue"};
這個之所以不能做自加運算,正如你所說這樣的初始化方式使得arr是一個指針數(shù)組,arr同時也是數(shù)組首地址,是常量不是左值,既然不是左值當然也就不能做自加操作。而且這里容易被const修飾影響,雖然這在這里不是引起這個問題的原因,去掉還是不能編譯的。
而
char const* argv[];
上面的聲明可以做自加運算應該是因為main函數(shù)的聲明是
int main(int argc, char **argv);
所以你現(xiàn)在使用的這種聲明被轉(zhuǎn)化了,雖然兩種表現(xiàn)形式是一樣的,但是前者是二維指針而非指針數(shù)組,也就可以做自加運算。
- 2 回答
- 0 關注
- 191 瀏覽
添加回答
舉報