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