首页
社区
课程
招聘
关于C语言中必须要用到指针的讨论
发表于: 2015-4-20 11:34 9057

关于C语言中必须要用到指针的讨论

2015-4-20 11:34
9057
新手自学,只有汇编基础,学C语言学了很长时间了。
   每个人都说指针是C的灵魂,指针很厉害。

可是我为什么感觉指针根本没必要存在?  

指针实质是变量,比如:
char a[10];
char *p=a;

既然a[0]可以访问数组了,为什么一定要*p来访问呢?

难道就为了灵活一点?引入这么大的一个概念?

C我也学了很长时间了,指针我也特意加重学习时间和深度。

因为函数return只能返回一个值或者表达式。所以在需要在被调函数内改主调函数内的变量时必须要用指针(因为C的函数只能通过函数参数值传递)外,没感觉哪里一定,必定要用到他。以下程序肯定实现不了交换m,n的。
void Exchange(int, int);

void Exchange(int a, int b)
{
    int c;

    c = a;
    a = b;
    b = c;
}

int main(void)
{
    int m, n;

    scanf("%d %d", &m, &n);
    Exchange(m, n);
    printf("%d %d\n", m, n);
}

   可能我目前学的太少,所以用不到,论坛上也找了关于指针的必须性的文章也没找到,还是指针这个概念已经过时了?我已经萌生去学C++的想法了。
   坛友能否举几个必须要用指针的例子让我等新手解惑?

总结:
经过各位热心朋友的解答,我理出的结论。

指针是一个表示地址的变量,也就是内存地址。所以他不存在重要不重要,而是你要理解他的使用方式和表达的意思。指针就是变向的内存。下列代码也说明了这一点。

        int *p;
        int *p1;

        p = &a;
000B13FD 8D 45 F4             lea         eax,[a]  
000B1400 89 45 D0             mov         dword ptr

,eax  
        p1 = &b;
000B1403 8D 45 E8             lea         eax,  
000B1406 89 45 C4             mov         dword ptr [p1],eax  

        printf("the sum number:%d\n", z = *p1 + *p);
000B1409 8B 45 C4             mov         eax,dword ptr [p1]  
000B140C 8B 08                mov         ecx,dword ptr [eax]  
000B140E 8B 55 D0             mov         edx,dword ptr

  
000B1411 03 0A                add         ecx,dword ptr [edx]  
000B1413 89 4D DC             mov         dword ptr [z],ecx  
000B1416 8B F4                mov         esi,esp  
000B1418 8B 45 DC             mov         eax,dword ptr [z]  
000B141B 50                   push        eax  
000B141C 68 D4 59 0B 00       push        0B59D4h  
000B1421 FF 15 14 91 0B 00    call        dword ptr ds:[0B9114h]

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (37)
雪    币: 1392
活跃值: (4867)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
2
不用指针实现下面两个

有n个数据 需要按照大小排序输出
写一个函数打印结构体的数据

体会一下就知道了
2015-4-20 11:46
0
雪    币: 49
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
指针我觉得最神奇之处在于,你可以随意的操纵内存,而不是拘泥于那些语法。如果你理解了内存模型与指针之间的联系,其余那些语法,用用两遍就熟了。
2015-4-20 12:18
0
雪    币: 20
活跃值: (42)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
第一个按大小输出,不用指针也可以啊,但是很难实在高质量通用的函数,如果数组n[10]=[0,1,2...9]排序不用指针也可以的。第二个不用指针也可以啊,有结构体名.结构体内的值也不需要通过指针呀。
2015-4-20 12:44
0
雪    币: 20
活跃值: (42)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
5
没学过内在模型,能否给个有注解的代码
2015-4-20 12:45
0
雪    币: 1392
活跃值: (4867)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
6
麻烦你写个函数原型 试试,内部不要代码只要 参数 返回值,这个简单吧.
第一个我看看你怎么写
2015-4-20 12:48
0
雪    币: 231
活跃值: (663)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
返回多个值用指针最方便,用结构体会造成类爆炸
int add(IN int i,OUTOPT int* old){if(old){*old=i;}return i+1;}
2015-4-20 13:11
0
雪    币: 20
活跃值: (42)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
8
C.A.R.Hoare的快速排序算法,折半的就可以啊,没有用指针,也可以说用数组代替了指针吧。

我写一个吧。

//以函数递归调用自身完成递增顺序对V[left].....v
进行排序
void qsor(int v[], int left, int right)
{
        int i, int last;

        void swap(int v[], int i, int j);

        if (left >= right) //若数组元素少于2个退出
                return;

        swap(v, left, (left + right) / 2);  //划分子集的元素

        last = left;                       //移动到V[0]

        for (i = left + 1; i <= right;i++) //划分子集

        if (v[i] < v[left])

                swap(v, ++last, i);
       
        swap(v, left, last);                 //恢复划分子集的元素

                qsor(v, left, last - 1);
            qsor(v, last + 1, right);

}
2015-4-20 13:57
0
雪    币: 62
活跃值: (946)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
指针的存在是因为类和结构体。

1.函数传参的时候,你如何传一个结构体/类,让函数里外操作的是同一块内存?必须用指针。

2.利用指针可以格式化变量类型,只要你知道变量在内存中的本质。所以你可以很方便的把某块内存格式化为某种类型的数据。例子之一是解析PE格式。

简单思考了一下,欢迎大家补充。
2015-4-20 13:58
0
雪    币: 20
活跃值: (42)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
10
这算一个灵活的案例,可以返回一个地址。还有别的吗?感觉这不足以让指针称霸C的原因。包括间接访问也不足。。。。
2015-4-20 14:00
0
雪    币: 20
活跃值: (42)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
11
第一个我在提问里已经写了,特殊的参数传递要求必须要用指针。
第二个能解释一下吗?PE没有接触过。

这问题是不是应该等我学完很多东西后再问呀,但是,我觉得他无用就不想学他了。
2015-4-20 14:02
0
雪    币: 70
活跃值: (37)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
指针的核心是可以操作内存,明白这个就行了
2015-4-20 14:15
0
雪    币: 1392
活跃值: (4867)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
13
[QUOTE=sentaly;1366260]C.A.R.Hoare的快速排序算法,折半的就可以啊,没有用指针,也可以说用数组代替了指针吧。

我写一个吧。

//以函数递归调用自身完成递增顺序对V[left].....v
进行排序
void qsor(int v[], int left, int right)
{
        int i, ...[/QUOTE]

int v[] 就是指针
至于结构体不用指针就需要重新拷贝一份内存 浪费空间和时间。
包括像双向链表,一旦拷贝就会出问题。必须用指针
2015-4-20 14:21
0
雪    币: 20
活跃值: (42)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
14
可有具体实例?可能我没有学过内存这一块。我目前学的知识里变量也是要分配内存的。包括常量等等 。能个实例看下最好了。
2015-4-20 14:23
0
雪    币: 20
活跃值: (42)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
15
[QUOTE=IamHuskar;1366266]int v[] 就是指针
至于结构体不用指针就需要重新拷贝一份内存 浪费空间和时间。
包括像双向链表,一旦拷贝就会出问题。必须用指针[/QUOTE]

这里v[]和指针是同样的作用,v[]和指针还是有区别的,V[]是常量,指针是变量。

可是我还是感觉缺少一种一锤定音的那种感觉。类似于switch 缺少default:一样。
2015-4-20 14:27
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
可以直接操作内存  可以让一切数据变成你想要的东西  包括恶意代码哦
2015-4-20 14:33
0
雪    币: 62
活跃值: (946)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
17
不用直接学指针,用到了自然会懂。

另外我提一点,你可以用VS带源码调试,看汇编,你就知道指针是存在于汇编之中的。而你在代码中使用指针,就类似你在代码中内嵌汇编一样。所以这个问题可以转换为:为什么要在源码中内嵌汇编?

2015-4-20 14:37
0
雪    币: 20
活跃值: (42)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
18
我想要例子,代码片段也可以啊
2015-4-20 14:44
0
雪    币: 65
活跃值: (112)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
19
[QUOTE=sentaly;1366227]新手自学,只有汇编基础,学C语言学了很长时间了。
   每个人都说指针是C的灵魂,指针很厉害。

可是我为什么感觉指针根本没必要存在?  

指针实质是变量,比如:
char a[10];
char *p=&a;

既然a[0]可以访问数组了,为什么一定...[/QUOTE]

先搞清楚指针的实质是什么:指针等价于内存;操作指针等价于操作内存。
接着搞清楚程序代码的实质:不考虑寄存器等资源,整个程序的生命周期就是在对内存进行各种操作,没有例外。

指针不需要存在?
2015-4-20 14:47
0
雪    币: 20
活跃值: (42)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
20
        int *p;
        int *p1;

        p = &a;
000B13FD 8D 45 F4             lea         eax,[a]    //传送[a]的地址给eax
000B1400 89 45 D0             mov         dword ptr

,eax  //把eax内的地址值传送给内存地址


        p1 = &b;
000B1403 8D 45 E8             lea         eax,  
000B1406 89 45 C4             mov         dword ptr [p1],eax  

        printf("the sum number:%d\n", z = *p1 + *p);
000B1409 8B 45 C4             mov         eax,dword ptr [p1]  
000B140C 8B 08                mov         ecx,dword ptr [eax]  
000B140E 8B 55 D0             mov         edx,dword ptr

  
000B1411 03 0A                add         ecx,dword ptr [edx]  
000B1413 89 4D DC             mov         dword ptr [z],ecx  
000B1416 8B F4                mov         esi,esp  
000B1418 8B 45 DC             mov         eax,dword ptr [z]  
000B141B 50                   push        eax  
000B141C 68 D4 59 0B 00       push        0B59D4h  
000B1421 FF 15 14 91 0B 00    call        dword ptr ds:[0B9114h]  

汇编下的指针很明了,把地址赋值给寄值器。。。就这么简单。

2015-4-20 14:52
0
雪    币: 69
活跃值: (270)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
msf
21
指针说白了就是个内存的索引,怎么用就看你了。
2015-4-20 14:55
0
雪    币: 20
活跃值: (42)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
22
我知道指针很有用,只是不了解他的用处到怎样重要,太抽象了点。你说的第一个我好像懂了,因为指针是地址,内存也同样是地址,所以指针可以说是内存的一种简明的表现方式。
第二个怎么理解呢?
2015-4-20 14:56
0
雪    币: 6
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
为什么c语言要用指针呢?其实不是为什么c言语要指针,而是现在的计算机编程就必须得用指针,指针是我们的说法,本质是操作内存,所以到目前为止,编程是离不开指针的,那些所谓没有指针的言,也只是把指针封装了而已,只是你看不到指针,其实还是有指针的,它们换了种说法——引用,区别就是你只管分配内存,其它的由相关的垃圾处理什么的处理。当然,如果想不用指针而转去学C++的话,还是不要去转了,C++也离不开指针的
2015-4-20 15:24
0
雪    币: 20
活跃值: (42)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
24
恩,谢谢,明白了。
2015-4-20 15:50
0
雪    币: 3723
活跃值: (594)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
25
既然你也学过汇编,那就明白指针(x86)不过是4个字节而已.
那只是提供的一种功能,开发者完全可以按照自己的方式去处理自己的代码.
2015-4-20 16:07
0
游客
登录 | 注册 方可回帖
返回
//