;
Hello,ello,o
格式:
char* na[N] = {"li", "zh", "li", "zh", "li"};
char *a[]
:表示a是数组,数组中的元素是指针,指向char类型,(数组里面所有的元素是连续的内存存放的)
数组名是数组第一个字节的内存地址,并且数组名a也表示指针。所以a 并不表示a地址存储的内容, 而是a地址本身。
a+1
:表示 a 的第二个元素的内存地址, 所以是加 8 字节。( 因为a的元素是char 指针, 所需要的空间为8字节(64位内存地址)。 )
*(a+1)
:则表示a这个数组的第二个元素的内容 (是个char 类型的指针,本例表示为world字符串的地址)。
*(*(a+1))
:则表示a这个数组的第二个元素的内容(char指针)所指向的内容(w字符).
char * a[10]
:表示限定这个数组最多可存放10个元素(char指针), 也就是说这个数组占用10*8 = 80字节。
#w: a+1 => *(a+1) => *(a+1)[0]
指针(地址) 指针内容(字符串) 字符
char *argv:理解为字符串
char **argv:理解为字符串指针
char *argv[]:字符串指针数组
int main(int argc, char*argv[])
这是一个典型的数组名(或者说是指针数组)做函数参数的例子,而且还是没有指定大小的形参数组。
有时为了再被调用函数中处理数组元素的需要,可以另设一个形参,传递需要处理的数组元素的个数。而且用数组名做函数实参时,不是吧数组元素的值传递给形参,而是把实参数组的首元素的地址传递给形参数组,这样两个数组久共同占有同一内存单元。 和变量作函数参数的作用不一样。
可以去看看关于数组作为函数参数和指针数组作main函数形参方面的例子。谭浩强的那本书讲的很细,对这个有详细的解释。
1. 当 char [] 作为函数的参数时, 表示 char *. 当作为函数的参数传入时, 实际上是拷贝了数组的第一个元素的地址。
所以 void test (char a[]) 等同于 void test ( char * a )
char x[10] ;
然后调用 test(x) 则等同于把 x 的第一个元素的地址赋予给参数 a。
2. char * a 和 char a[]
相同点 : a都是指针, 指向char类型。
不同点 : char a[] 把内容存在stack。char *a 则把指针存在 stack,把内容存在 constants。
3. char * a[10] 和 char a[10][20]
相同点 : a 都是2级指针, *a 表示一级指针, **a 表示内存中存储的内容。
不同点 : char * a[10], 数组由char * 类型的指针组成; char a [10][20] 表示一位放10个元素, 二维放20个元素, 值存放地是一块连续的内存区域, 没有指针。
4. 小窍门 : [] 和 * 的数量对应, 如 char a[][] 的指针层数是 2, 相当于 char **a; char *a[] 也是如此, 两层指针. 迷糊的时候数数到底有几个 * 几个 [], 就知道什么情况下存储的是内容还是地址了 ? 如 char a[][] 的情况里面: &a, a, *a 都是地址, **a 是内容。