当我阅读有关C语言的书籍时,双重指针让我很困惑。
char s[5][5];
char *s[5];
char (*s)[5];
那么它们之间有什么区别呢?
在C语言中,最好对声明进行清晰的表达,以使其更加直观。为此,您需要遵循右左阅读的约定。以下是其方法:
char *s[5];
你如何说出它?首先从变量名s
的右侧开始,然后向左移动。所以你从说"s是一个/一"开始。在右边,你看到了一个[]
,然后说"s是一个数组..."。然后你再向左移动,看到了*
,并说"s是一个指针数组。"这就是它的含义。它是一个由5个指针组成的数组。你可以在这个数组中存储不同的指针。
现在是另一个:
char (*s)[5];
你可以按照同样的逻辑开始。先说“s是一个”,然后看 ()
中的内容,括号内的任何内容都比括号外的内容更接近 s
。因此,*
比 []
更接近 s
。现在你可以说,“s 是一个指针……” 然后走出括号看 []
。接着继续说,“s是指向数组的指针”。这正是它的含义。这是一个指针,将指向数组的第一个元素。int (*callme)(int a, int b)
int (*callme[10])(int a, int b)
提示:最后一个可以用来创建函数的查找表。
编辑:
正如评论中提到的,开头也有一个 char
。我从来没有找到一种简单的方法来说明这个,但通常从上下文中很清楚。例如,在第一个示例中,char
定义了数组的类型,而在第二个示例中,它定义了指针。在我发布的练习中,int
定义了函数返回值的类型。通常,对于这样的定义,将恰好有一个未定义类型的项。这就是我找出类型所在的位置的方式。
char
;char *s[5]
不是任何类型的 5 个“不同指针”的数组,它具体是一个指向 char
的 5 个指针的数组。 - Dour High Archa
也不需要 b
。(int, int)
就足够了。 - David C. Rankin虽然已经介绍了declaration,但也应该指出用法上的差异:
char s[5][5];
--
s
指向分配的内存区域(如果是全局的则在堆中,如果是局部的则在栈中),s[0][0]
.. s[4][4]
(或者在 s[0]
.. s[24]
)处写入高达25个字符值,sizeof(s)
== 25。char *s[5];
--
s
指向分配的内存区域(如果是全局的则在堆中,如果是局部的则在栈中),s[0]
.. s[4]
处写入高达5个指针值,sizeof(s)
== 40 (*)。char (*s)[5];
--
s
并没有指向任何分配的内存——在这一点上,它只是一个未初始化的指针。&s
写入一个指针值。sizeof(s)
== 8 (*)。(*) 注意:假设是64位架构。
char(*s)[5]
只是一个指针吗?char *s
,char (*s)[5]
和char (*s)[10]
之间有什么区别吗? - storenchar (*s)[5]; char arr[2][5]; s = arr;
这里 s 指向的是 arr 的第一行,长度为 5 的数组。如果你执行 s++,那么 s 就会指向 arr 的第二行。2. char *s; char arr[5]; s = arr;
这里 s 指向的是数组的首个元素,就是一个字符。如果你执行 s++,它就会指向下一个字符。 - didoint * a
类型时,编译器不仅存储值a
,还存储a
的类型,因此可能会有一些额外的内存开销。 - storen
char * s [5];
。 - aroth