打印地址和值是查看它们的合理方法。但是,如果您可以启动并运行调试器,那就更好了,因为您可以更快地跟踪指针,观察它们在您单步执行时的变化,等等。
如果您熟悉 Windows 中的“快捷方式”或 Linux 文件系统中的软链接,那么在您开始使用时,将指针视为另一个对象(无论该对象是是一个结构体、一个内置类型、另一个指针等)。
快捷方式仍然是一个文件。它在磁盘驱动器上占用自己的空间,它引用另一个文件,并且可以修改它以引用与以前不同的文件文件。类似地,C 中的指针是一个占用内存的对象,包含另一个内存位置的地址,并且可以通过分配给它来更改为包含不同的地址。
一个区别是,如果您双击快捷方式,它的行为就好像您双击了它指向的内容一样。指针的情况并非如此 - 您始终必须使用“*”或“->”显式取消引用指针才能访问它指向的内容。另一个区别是,在 C 中使用指向某些内容的指针是很常见的。
至于行话,不幸的是你只需要学习它。 “int doSomething(char **hihi)”的意思是“一个名为 doSomething 的函数,它返回一个整数,并以一个指向 char 的指针作为参数”。关键的一点是“char ** hihi
" 的意思是“一个指向字符的指针。我们将把指针指向字符的指针称为“hihi”。您说 hihi 的“类型”是 char**,而 *hihi 的“类型”(当您取消引用指针时得到的)是char*,**hihi 的类型是 char。
在 C 中,指向 char 的指针通常表示字符串(换句话说,它是指向以 NUL 结尾的数组中第一个字符的指针)。通常“char *”表示“字符串”,但并非必须如此。它可能只是意味着指向一个字符的指针。有点像 Windows 中 1 字节文件的快捷方式(无论如何,对于 FAT32),C 中指向 char 的指针实际上比它指向的东西大:-)
同样, char** 通常不仅意味着指向一个字符串指针的指针,还意味着指向一组字符串指针的指针。可能不会,但如果确实如此,那么下面的小图可能会有所帮助:
hihi
____ ____ ________ _________ _______
|____| -----> |____| *hihi ---> |___A____| |___B_____| |___C___|
|____| *(hihi+1) ------------------^ ^
|____| *(hihi+2) ---------------------------------|
| ...| etc.
hihi 指的是塔式块的工作,这是我表示指针数组的方式。正如您已经指出的,我可以写 hihi[0] 代替 *hihi,hihi[1] 代替 *(hihi+1),等等。
这是一个连续的内存块,其中每个指针大小的块都包含另一个内存块的地址(即,它“指向”),该内存块位于天知道在哪里,包含一个或多个字符。所以,hihi[0]是字符串A的第一个字符的地址,hihi[1]是字符串B的第一个字符的地址。
如果 hihi 不指向数组,而只是指向单个指针,那么塔楼就是平房。同样,如果 *hihi 不指向字符串,只指向一个字符,那么细长的块就是一个正方形。您可能会问,“我怎么知道塔楼有多少层?”。这在 C 编程中是一件大事 - 通常函数文档会告诉你(它可能会说“1”,或“12”,或“足以完成你告诉我要做的事情”,否则你会通过楼层数作为额外参数,否则文档会告诉您该数组是“NULL 终止的”,这意味着它将继续读取,直到看到地址/值 NULL,然后停止。main 函数实际上执行以下两个操作:第二件事和第三件事 - argc 包含参数的数量,and为了安全起见,argv 是以 NULL 结尾的。
因此,每当您看到指针参数时,您都必须查看该函数的文档,以了解它是否需要指向数组的指针,如果是,则该数组必须有多大。如果你不小心这一点,你将创建一种称为“缓冲区溢出”的错误,其中一个函数需要一个指向大数组的指针,你给它一个指向小数组的指针,它会在末尾乱写乱画你给它的东西并开始破坏记忆。