0

今天遇到一个问题,在C语言中定义了一个指针数组:
char *words[4]={"aaaa","bbbb","ccccc","dddd"}
然后使用words[2]能直接拿出字符串cccc这个值,但是使用*(words[2])
发现拿出来的却是字符c
我的理解是 words[2]里面存储的是指向字符串"cccc"的指针 用words[2]拿出来的是地址,用*(words[i])拿出来的是指针的值,但是发现却完全不是这个情况 ,为什么呢?

4个回答

2

c指向数组的指针保存的是首元素的地址。

1

这个很好理解,我们来将问题拆分一下,首先是定义个字符串:
char *w = "aaaa";
那么定义完成之后*w得到的就应该是a,因为w存储的是字符串的首地址,它的类型是指向字符的指针,表达式*w拿到的正是这个地址中存储的字符a
然后是定义字符串数组:
char *words[] = {"aaaa","bbbb"};
words中存储的其实是一堆指针,这一堆指针组成了一个数组,其中words[0]这个指针正是第一个字符串的首地址,然后*(words[0])又回到第一个问题中了,这不就是第一个问题中的*w吗?

0
char *words[4]={"aaaa","bbbb","ccccc","dddd"};
// 这是一个指针数组 里面存着4个 char*指针 分别指向4个字符串常量首字母地址
// 你说words[2] 是什么? 一定是"ccccc" 字符串首字符的指针地址
// 既然words[2]是个地址 *words[2] 就是这个地址指向的值了
0

这就是个二级指针,或者说二维数组。

char *word[4] = {......};   // 题主的写法
char **word = {......};   // 另一种等效的写法

第二种如果不看赋值的内容是不是根本不知道这个字符串数组有多大?其实第一种也是,这就是我想说的,这个写法有坑。
现在没问题是因为声明的同时赋了初值,编译器根据初值的尺寸决定了数组所指向数据对象的大小,如果这样写习惯了,某一天写成这样:

char **word;  // 它可以合法的存储几个字符? 0个
//或者这样写:
char *word[4]; // 坑来了!它同样只能合法的存0个字符

原因在于没有声明第一级指针所指向数据对象的大小,问题描述中的数组由于有初值,所以编译器知道这个word数组中:
word[0] 指向5个char大小的数据对象(的首地址)
word[1] 指向5个char大小的数据对象(的首地址)
word[2] 指向6个char大小的数据对象(的首地址)
word[3] 指向5个char大小的数据对象(的首地址)

不知道题主看的是什么书,但是我知道的C语言最好的入门书是C Primer Plus,如果书不行,趁早换。
(与这本书相对的是谭浩x系列,俗话说左手谭刚强,右手打火机,哪里不会点哪里!)
我也不知道是哪儿的俗话。。。。。

撰写答案