指针的运算

其实,在C语言中,指针功能的强大,主要体现在指针变量的间接运算上,指针涉及的运算并不多。

1、基本运算

指针变量的基本运算包括赋值、取地址以及取值(间接运算)等运算。

举例,如清单1:

[cpp] view plain copy

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. int a = 5;
  5. int *p = &a;
  6. int b = *p;
  7. *p = 9;
  8. printf("p = %p, &a = %p, &p = %p\n", p, &a, &p);
  9. printf("a = %d, b = %d\n", a, b);
  10. return 0;
  11. }

例子输出结果:

[cpp] view plain copy

  1. p = 0xbfee8388, &a = 0xbfee8388, &p = 0xbfee8384
  2. a = 9, b = 5

第6行的意思是把整型变量a的地址赋给指针变量p(这时可以说p指向了a),然后使用间接运算符(*),像第8和第9行那样,通过p来间接地使用a。

第5行的语句再平常不过了,其实是有深意的,在大多数编程语言中用同一符号(如变量名a)来表示它的地址和地址中的内容(即值),编译器根据上下文环境来判断它的具体含义。如例子中的第8行的意思是把变量a的值(即整数5)赋给b(在这种情况下a被叫做右值),而第9行的意思是往a的地址(即0xbfee8388)中存储一个整数9(在这种情况下a被叫作左值),所以变量既可作为左值,也可作为右值。

指针变量作为一种变量,当然既可以给它赋值(如例子中把变量a的地址赋给指针变量p),也可以通过取址运算符(&)来取它的地址(如第11行打印出指针变量p的地址值0xbfee8384)。

取值运算的复杂用法,如清单2:

[cpp] view plain copy

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. void func(char **p, int num)
  5. {
  6. *p = (char *)malloc(num);
  7. }
  8. int main(void)
  9. {
  10. char *str = NULL;
  11. func(&str, 20);
  12. strcpy(str, "hello world!");
  13. printf("%s\n", str);
  14. free(str);
  15. return 0;
  16. }

例子输出结果:

[cpp] view plain copy

  1. hello world!

在例子中的第14行,通过函数调用把指针变量str的地址赋给二级指针变量p,然后在第7行通过*p来间接地使用str,这时str中的值为所分配的20个字节内存的首地址,接着往这段内存中拷贝字符串,最后打印字符串并释放这段内存。

2、加减和求差

指针变量加1的意义与整型变量加1的意义不同。

举例,如清单3:

[cpp] view plain copy

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. int a[] = {18, 17, 16, 15, 14, 13, 12, 11};
  5. int *start = a, *end = &a[7];
  6. printf("address start = %p, end = %p\n", start, end);
  7. printf("*(start+2) = %d, *(--end) = %d\n",
  8. *(start+2), *(--end));
  9. printf("(--end) - (start+2) = %d\n", (--end) - (start+2));
  10. return 0;
  11. }

例子输出结果:

[cpp] view plain copy

  1. address start = 0xbfeabab8, end = 0xbfeabad4
  2. *(start+2) = 16, *(--end) = 12
  3. (--end) - (start+2) = 3

首先使用指针变量start和end分别指向数组a的第一个元素和最后一个元素,然后从start+2(即0xbfeabac0,通过式子0xbfeabab8+2*sizeof(int)算出)的地址中取得整数16,和--end(即0xbfeabad0,通过式子0xbfeabad4-1*sizeof(int)算出)的地址中取得整数12,从中可知,指针变量加1是加一个数据类型(就是声明指针变量时所使用的数据类型)的大小。

指针变量求差的意义不大,可以得到数组两个元素之间的距离,如例子中元素7和元素3相隔3个元素。

3、比较

指针变量的比较就是比较指针变量值的大小以及是否相等,与其他数据类型的比较类似。

如清单4:

[cpp] view plain copy

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main(void)
  4. {
  5. char *p = (char *)malloc(10);
  6. if (p == NULL)
  7. printf("failed to allocate memory.\n");
  8. else
  9. printf("allocate memory successfully.\n");
  10. free(p);
  11. return 0;
  12. }

例子输出结果:

[cpp] view plain copy

  1. allocate memory successfully.

例子中,若malloc的返回不为NULL即表示内存分配成功。

时间: 2024-10-04 06:22:15

指针的运算的相关文章

C语言指针——指针的运算

说指针之前,先说两个比较不相关的东西,也当做是一种知识的补充.看下面的代码: #include <stdio.h> int main(void) { char *s = "Hello world."; printf(s); } 运行这段代码,会出现错误吗?如果出现错误,是什么错误? 分析:printf一种常规的用法就是printf("Please input a data:");这种用法相信很多人都使用过,但是将这种用法分析一下,这样的用法printf函

#运算符、不同的指针类型、数组和指针、指针运算、堆、栈、静态区、只读区、下标VS指针

#运算符:用于在预编译期将宏参数转换为字符串 #define CONVERS(x)  #x   //注:没用双引号包括. 不同类型的指针占用的内存空间大小相同. 局部变量 定义: a[5]; 打印a[i]时,a[i]为随机数. 若定义a[5]={1,2}; 打印时,a[0]=1;a[1]=2;a[2]=a[3]=a[4]=0; 数组地址与数组名: 1.数组名代表数组首元素的地址.  a=&a[0]; 2.数组的地址需要用取地址符号&才能得到 (&a) 3.数组首元素的地址值与数组的

数组与指针

//使用递归来计算阶乘#include<stdio.h>long rfact(int n);int main(){ int num; printf("This program calculate factorials.\n"); printf("Enter a value in the range 0-12(q to quit): \n"); while(scanf("%d",&num)==1) { if(num <0

指针数组和数组指针

指针数组:首先它是一个数组,数组的元素都是指针.它是“储存指针的数组”的简称.int *p1[10];数组指针:首先它是一个指针,它指向一个数组.它是“指向数组的指针”的简称.   int (*p2)[10]; 这里需要明白一个符号之间的优先级问题,关键在于p1.p2先和谁结合.“[]”的优先级比“*”要高.p1 先与“[]”结合,构成一个数组的定义,数组名为 p1,int *修饰的是数组的内容,即数组的每个元素.那现在我们清楚,这是一个数组,其包含 10 个指向 int 类型数据的指针,即指针

c++指针 笔记

我们定义一个指针就一定要用他保存一个内存地址,加入我们不这样做,那么该指针就是一个失控指针他可以指向任何地址,并且对该地址的数值进行修改或删除,后果是非常可怕的解决办法是将该指针初始化为0,即p = 0:该语句是将p所保存的地址清零,(即让p指向00000000这个地址,这个地址是不会存放任何数据的,因此我们对它进行的任意操作都不会产生严重后果)这样p就不会因为我们的疏忽而修改它指向的地址(随机)的值 由于指针类型不同决定了指针的运算方式不同,所以我们不能将一种类型的指针赋给另一种类型的指针 可

[C/C++基础--笔试突击] 7.指针与引用

概述: 比较抽象的但又很有用的东西 0.0 void*指针:可以保存任何类型对象的地址. 指向指针的指针 函数指针 7.1 指针 一个有效的指针必然是一下三种状态之一: 1)保存一个特定对象的地址: 2)指向某个对象后面的另一个对象 3)0值. 若指针保存0值,表明它不指向任何对象.未初始化的指针是无效的,直到给该指针赋值后,才可使用. 注:*p++和(*p)++不等价,单目运算符*的优先级比++高,故*p++先完成取值操作,然后对指针地址执行++操作,而(*p)++是首先执行屈指操作,然后对该

由typedef和函数指针引起的危机

由typedef和函数指针引起的危机 昨天阅读了大神强哥的代码,发现里面用到了函数指针,也用到的typedef.本来我自以为对这两个概念有一定的认识,但是突然发现这两个东西居然用到了一起!!!!(在一起了也不说一声,一点心理准备都没有): typedef int (* fp)(void *para, void *end); 瞬间就蒙了,这是个啥东西???于是我开始看书,上网查资料,想弄明白.在这个过程中,我发现自己不仅仅是对这两个概念理解不够!!!而是,对数组.指针.变量的理解都不够.这引发了我

2017年 1月 15日 指针 学习整理

有关指针的概念: 指针是一个特殊的变量,它里面存储的数值被解释为内存里的一个地址. FIrst of all:我们需要明确目标 关于指针的学习以及使用我们需要搞清楚有关指针的四个内容:指针的类型,指针所指向的类型,指针的值(或者说叫指针所指向的内存区),还有指针本身所占用的内存区(指针也是一个特殊的变量吗,它肯定也是占据内存的).接下来让我们分别进行学习. 我们先来申明几个指针的例子: 1 int *ptr; 2 char *ptr; 3 int **ptr; 4 int (*ptr)[3];

附录一 再论指针和数组

附录一 附录一 再论指针和数组 再论指针和数组 [email protected]:Kevin-Dfg/[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git 预习检查 链表单元有哪几个部分组成 如何申请链表单元,及释放链表单元 实现单链表插入的基本语法 简述一下快速排序基本理论要点 [email protected]:Kevin-Dfg/[email protected]:Kevin-Dfg/Dat