Re: [问题] 自己练习运用基础的指标小问题

楼主: Feis (永远睡不着 @@)   2015-08-05 06:03:03
※ 引述《M013020058 (帅翰)》之铭言:
: 非常感谢先进的分析
: 目前初学者小弟我为指标分类为下,并提出几个疑惑的地方。
: 1, 很多书籍都透过变量位址来修改/定义变量资料,但今天不是直接修改/定义变量资料
: 就好?为什么要绕一圈?
诚如之前所提到的,主要有两个方向,一个是你不用指标做不到,另一个是这样做可能
比较快。
后者牵涉到的问题比较多,而且也不是主要的用途,所以我讲一下前者。
首先我们知道,在 C 里面你要存取某个物件/变量的值的时候,
你有两种方法,一个是你要写出他的名字,另一个是你要知道他的位址:
方法一: 使用名字
int main() {
int a = 3;
a = 5; // 透过名字去修改变量内容
// 此时 a 的值是 5
return 0;
}
方法二: 使用位址
int main() {
int a = 3;
int *b = &a;
*b = 5; // 透过位址去修改变量内容
// 此时 a 的值是 5
return 0;
}
上述两种方法都可以达到修改变量 a 内容的效果,而一般的时候我们会建议使用前者,
因为后者看起来就是绕了一圈不知道在干嘛。
那后者什么时候有用呢 ?
最常见的就是在函式呼叫的时候:
void f(int b) {
b = 5;
}
int main() {
int a = 3;
f(a);
// 此时 a 是 3 还是 5 ?
return 0;
}
初学者如果在学习函式的时候没有对引数传递和可视范围 (scope) 有比较清楚的了解,
那这个例子可能就弄不清楚应该是 3 或是 5
在呼叫完 f(a) 之后,main 里面的 a 应该还是 3,他不会受到 f 的影响。
这可以从很多面向来解释,首先呼叫函式的时候,a 会被复制一份变成 f 里面的 b,
所以 b = 5 修改的是一个复制品,无法修改到原始的变量 a。
那如果我们把 b = 5 改成 a = 5 呢 ?
void f(int a) {
a = 5;
}
结果还是一样没用,而 f 里面的 a 只是一个刚好同名同姓的复制品。
f 函式的定义是在 main 里面的 a 的可视范围外,所以是无法用变量名字直接去存取
main 里面的 a。
此时我们可以使用指标来逃过可视范围的限制,透过 "位址" 来修改变量内容:
void f(int *b) {
*b = 5;
}
int main() {
int a = 3;
f(&a);
// 此时 a 是 5
return 0;
}
为什么这里要特别传递指标呢? 就是希望 f 里面可以透过 "位址" 去存取 main 里面
的 a 。因为位址是个 "值",是可以复制到 f 里面的,没有跟名字一样有可视范围限
制。
还有什么时候我们可能会需要位址而不能用名字去存取呢 ?
我举个简化的例子:
int main() {
int a = 3;
int b = 5;
int c = 9;
int d = 4;
// 可能因为某些原因,我们当初没有宣告阵列而是使用四个独立的变量名字
// 如果现在我想要用循环去批次处理这些变量怎么办 ?
int* t[] = {&a, &b, &c, &d}; // 我们可以使用阵列去存变量位址
for (int i = 0; i < 4; i++) { // 此时就可以使用循环去依序存取不同名字的变量
f(t[i]);
}
return 0;
}
: 2,同上,是否是为了读写档案所建立指标功能?
不全然是,读写档案只是指标的一种应用。
因为读写档案的时候是使用函式传递、生命周期与可视范围脱钩、档案大小不固定、存
取有效能考量等等,用指标去操作是比较可能的设计。
: 3,以矩阵为例,可用指标来取代矩阵。而两种在内存上或其他地方哪里不一样?
你可能有什么误会
指标跟阵列的爱恨情仇有两个主要的问题:
一个是常见的存取问题,指标可以用来存取所指向的阵列元素。
实际上照 C 的阵列设计,所有阵列的存取都是透过指标。
其实没有什么取不取代的问题。
只是当你要在函式间传递阵列的时候,因为 C 函式无法直接传递阵列型别的物件,
所以你只能透过传递指标去存取。
另一个问题是空间配置问题,
阵列的大小如果是编译期已知,我们可以透过变量定义来配置:
int a[10];
但是如果在编译期还不知道的话,我们就需要透过动态配置:
int size;
scanf("%d", &size);
int *a = (int *) malloc(size *sizeof(int));
(C++ 或 C99 后有其他作法)
(注: 有些时候因为编译器的限制,在函式内能配置的阵列大小会受到限制,
此时也有可能改用后者来动态配置或者改为全域变量。)
所以实际上需要考量的是空间配置问题,看你是属于哪一种就用哪一个。
: 4, 最后,指标能有一般变量没有的“动态”功能,所以才需要指标?
不知道动态功能是什么意思 ?
: 在指标上的学习,小弟我一直在想这几个问题?为何需要指标?每本书籍都把指标列为程
: 式码重要的地方,无法理解~~~~~
因为你写太少练习,简单说就是如果你不需要用就可以把程式写好,看起来程式码又没有
乱七八糟。那就不要用指标。
初学者与其练习怎么用,不如先练习不要用怎么写 ?
PS:
我常开玩笑说,如果你完全不要用函式,那你大概就快不需要用指标了。
但是你要怎么不用函式呢 @@
了解函式呼叫的运作与限制是使用指标一个很重要的基础
作者: xjpjeass (人人)   2015-08-05 09:23:00
推,现在学指标真的会有点混乱
作者: KawasumiMai (さあ、死ぬがいい)   2015-08-05 17:01:00
一楼你把变量跟指标想成姓名跟住址就好了,要寄东西给某某人你可以指定拿给他,或寄到他家。前者是不管他在哪都会让他收到,后者是寄过去可能其实他搬走了但对邮差来说后者可以说几乎一定比较快。然后就是物件跟物件之间要沟通,你不用指标就是存一堆变量呼叫一堆方法然后return 来return去,但如果在初始化就把指标传过去记忆,就很方便呼叫其他物件不过用指标就要注意内存复写的问题,如同前面说的邮差寄信过去其实是别人收到。可能会出错或结果有误
作者: xjpjeass (人人)   2015-08-05 17:39:00
哇...谢谢川澄大的解释,用让自己有画面的方式来想会方便很多
作者: coal511464 (我一个人)   2015-08-05 19:01:00
好文
作者: chuegou (chuegou)   2015-08-05 22:13:00
我不用函式的话大概会是满满的go to
作者: MIKEmike07 (加油!)   2015-08-06 03:39:00

Links booklink

Contact Us: admin [ a t ] ucptt.com