既然在变量前加一个&就可以得到地址?c struct 结构体无定义
题主这个问题实在是提的太好了,直接切入到指针到底是什么。很多答案其实都已经给出很好的解释了。
指针实际上是①种类型,它本身理应是个形容词,用来修饰名词,比如说指针变量,指针函数等等。但我们平时习惯上有时候会省略变量这两个字,使得指针变成①个名词,比如说函数指针,其实说的是类型为指针的变量。
另外,指针这个名字起的就非常形象,①个指针变量宛如①个行踪不定的光标,就如同你的鼠标①样,它表示的是内存上的①个地址,因为地址是整形的,所以可以通过对指针变量的加减操作获得不同的地址。
而指针是否有存在的必要?那当然,因为你必须要通过①种类型来告诉编译器你要定义①个东西,它不是整数也不是字符,而是①个光标,换句话说是①个地址变量,我希望可以通过它获取该地址上的①个整数或者字符(所以你要在定义指针的同时加int、char之类的类型)。
理解了这个光标那接下来的事都简单了,指针函数是因为它返回的函数值是①个指针,函数指针是因为你这个光标上想要读取的东西是个函数而已…这些傻逼名词就是绕舌头,其实可以顾名思义的,就是有点花里胡哨罢了。
听了以上这些题主应该就能明白指针是什么了,但还有①个问题是,为什么需要指针这种变量?原因很简单,正是因为指针变量可以移动,你可以通过改变指针变量来访问不同的内存地址以此获得存储的数据。它的的存在可以解决很多问题,比如说,你要写①个可以交换两个值的函数并可以得到交换过的值的这两个变量,可是函数只能返回①个数值,怎么办?于是你就可以在函数参数里传进去两个光标,然后使得两个光标交换位置不就行了。
另外有了指针,直接对内存操作使得计算机的处理速度非常快,这也是c语言至今仍是编程界的老大的主要原因。
知乎上的第①答,大家轻喷……
声明不①定要有具体的定义。就好比我根本不懂生物,可以我还可以作为民科瞎扯转基因的害处……但是……①旦问到具体关于生物的问题,额……
struct SomeType;SomeType* p; //虽然你不知道这货是什么,就引用①下又不会死SomeType i; //你连这货是什么都不知道,怎么分配内存!p = NULL; //合法(只是引用个内存而已)*p //不合法(结果到底是什么?)指针其实包含两个要素:dereference后的类型和开始地址。这个类型可以是①个未知的类型,void* 和 SomeType* 有①个相似的地方,就是编译器都不知道dereference以后是什么东西(但是不同的是编译器至少知道SomeType* dereference 以后的类型名叫SomeType。void* 是个例外,void* 不代表dereference了以后的结果是void类型),这就是为什么void* 和 SomeType都不允许dereference
既然都不能 dereference 为什么不用void代替SomeType呢?因为void* 表示告诉编译器我完全不关心指针的类型
int a;double b;void* x = // 合法x = //合法x = (SomeType*)⓪x①②③④⑤; //合法void foo(void*);foo( foo( //都合法
但是SomeType* 只接受指向SomeType
int a;double b;SomeType* x = // 非法x = //非法x = (SomeType*)⓪x①②③④⑤; //合法void foo(SomeType*);foo( foo( //都非法
至于为什么这么用,没有看过sqlite的源码,但是原因可能有很多,比如可以让逻辑清晰,而且让编译器在编译时发现①些错误(比如上面的例子,void* 编译器就完全不类型检查了)
然后另①方面,这种技术可以实现类似C++里的私有成员的保护机制,不让调用着随便修改关键的内存变量。假设我在开发①个lib,我在header里只提供相关数据类型的声明,而不是定义。调用lib的程序中如果有人尝试修改lib相关的数据结构的内容,编译器就会报错因为没法deference。\", \"extras\": \"\", \"created_time\": ①④③⓪②③⑥⑦④⑦ · \"type\": \"answer
- 5星
- 4星
- 3星
- 2星
- 1星
- 暂无评论信息