一文搞懂C/C++中指针那些事(上篇)

一 指针变量

1.间接存取        指针变量的值为地址;普通变量的值为数据;其中“*”为指针运算符。&是地址操作符,用来引用一个内存地址。通过在变量名字前使用&操作符,我们可以得到该变量的内存地址。        针对内存数据的存取的两种方法:直接存取和间接存取,所谓的间接存取是指为了存取一个变量值,首先从存放变量地址的指针变量单元中取得该变量的存储地址,然后再从该地址中存取该变量值。直接上例子:

int x,*s; //定义了整形变量x;还定义了一个用于存放整形变量所占内存地址的指针变量s
s = &x;   //将x所占的内存地址取出赋给指针变量s
*s = 3;   //在s所指向的内存地址中赋以整型值3
//等价于
int x; x = 3;

2.指针变量定义与引用        一般形式: 类型标识符 *指针变量名

int *m,*n;
double *p,*q;
int *uninit;    // int指针未初始化
int *nullptr = NULL;   // 初始化为NULL
void *vptr;   // void指针未初始化

       注:C语言中,数组元素的下标是从0开始的。 例:

int main()
{
    double x=0.11,y=0.1;
    double *p,*q;
    p=&x;q=&y;
    printf("&x=%u,&y=%u\n",&x,&y);  //输出变量x与y的地址
    printf("p=%u,q=%u\n",p,q);     //输出指针变量存放的地址
    printf("x=%f,y=%f\n",x,y);     //输出X与y的值
    printf("*p=%f,*q=%f\n",*p,*q);  
    //输出指针变量p与q所指向的变量值,p是指针变量,不能说*p是指针变量
}

3.指针变量作为函数参数        例:交换两个变量值

void swap(int **a,int **b)
{
    int *t;
    t = *a;
    *a = *b;
    *b = t;
}
int main()
{
    int i=3,j=5;
    int *p = &i, *q = &j;
    printf("%d,%d,%d,%d\n",*p,*q,i,j);
    swap(&p,&q);  //实参p与q的指针单元的地址传递给了形参a与b,
    printf("%d,%d,%d,%d\n",*p,*q,i,j);
    getchar();
}

4.指向指针的指针        指向指针的指针就是指向指针变量的指针。

int x,*q,**p;
q = &x;
p = &q;
**p = 3;
//等价于
int x; x=3;

       例:交换变量的值

void swap(int **a,int **b)
{
    int *t;
    t = *a;
    *a = *b;
    *b = t;
}
int main()
{
    int i=3,j=5;
    int *p = &i, *q = &j;
    printf("%d,%d,%d,%d\n",*p,*q,i,j);
    swap(&p,&q);  //实参p与q的指针单元的地址传递给了形参a与b,
    printf("%d,%d,%d,%d\n",*p,*q,i,j);
    getchar();
}

总结:这里可以把指针、引用和值的关系类比为信封、邮箱地址和房子。一个指针就好像是一个信封,我们可以在上面填写邮寄地址。一个引用(地址)就像是一个邮件地址,它是实际的地址。取值就像是地址对应的房子。我们可以把信封上的地址擦掉,写上另外一个我们想要的地址,但这个行为对房子没有任何影响。

二 指针数组

       指针数组定义如下:类型标识 *数组名[数组长度说明]        例如: int *p[4];

int main()
{
    int a[5]={1,2,3,4,5};
    int *num[] = {&a[0],&a[1],&a[2],&a[3],&a[4]};
    int **p,k;
    p = num;  //等价于p=&num[0]
    for(k=0;k<5;k++)
    {
        printf("%5d",**p);
        p++;
    }
    printf("\n");
    getchar();
}

程序运行结果 : 1 2 3 4 5        以下四个说明语句是等价的:

int a[10],*p=a;
int a[10],*p=&a[0];
int a[10],*p; p=a;
int a[10],*p; p=&a[0];

三 指针与结构体

       就像数组一样,指向结构体的指针存储了结构体第一个元素的内存地址。与数组指针一样,结构体的指针必须声明和结构体类型保持一致,或者声明为void类型。

struct person {
  int age;
  char *name;
};
struct person first;
struct person *ptr; 
first.age = 26;
char *fullname = "full name";
first.name = fullname;
ptr = &first; 
printf("age=%d, name=%s\n", first.age, ptr->name);

第1至6行声明了一个person结构体,一个变量指向了一个person结构体和指向person结构体的指针。 第8行为age成员赋了一个int值。 第9至10行我们声明了一个char指针并赋值给一个char数组并赋值给结构体name成员。 第11行我们把一个person结构体引用赋值给结构体变量。 第13行我们打印了结构体实例的age和name。这里需要注意两个不同的符号,’.’ 和 ‘->’ 。结构体实例可以通过使用 ‘.’ 符号访问age变量。对于结构体实例的指针,我们可以通过 ‘->’ 符号访问name变量。也可以同样通过(*ptr).name来访问name变量。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏计算机视觉

Python 函数使用记录,join函数和os.path.join用法

1.join()函数 语法:‘sep’.join(seq) 参数说明: sep:分隔符。可以为空 seq:要连接的元素序列、字符串、元组、字典等 上面的语法即:...

2667
来自专栏desperate633

浅谈javascript中的的闭包作用域链引出闭包利用闭包突破作用域链的三种方法小结

闭包可以说是javascript中最令人迷惑的概念了。需要我们在实践中去慢慢理解,在实际编码中,由于闭包的效率和会产生大量无法销毁的内存,所以原则是尽量少使用闭...

621
来自专栏Java帮帮-微信公众号-技术文章全总结

04.Java对象和类

04.Java对象和类 Java 对象和类 Java作为一种面向对象语言。支持以下基本概念: 多态 继承 封装 抽象 类 对象 实例 方法 重载 本节我们重点研...

4256
来自专栏和蔼的张星的图像处理专栏

50. 数组剔除元素后的乘积两个遍历

给定一个整数数组A。 定义B[i] = A[0] * ... * A[i-1] * A[i+1] * ... * A[n-1], 计算B的时候请不要使用除法。...

904
来自专栏程序员互动联盟

【python基础】python自定义函数五种用法

Python自定义函数是以def开头,空一格之后是这个自定义函数的名称,名称后面是一对括号,括号里放置形参列表,结束括号后面一定要有冒号“:”,函数的执行体程序...

2844
来自专栏java 成神之路

局部变量和常量的性能分析

2628
来自专栏java工会

Java基础第一阶段知识点,招实习的面试官都在问这些

a) 答:Java源文件被编译成字节码的形式,无论在什么系统环境下,只要有java虚

881
来自专栏开源优测

[快学Python3]if条件控制

if语句 先看下Python中一般的条件控制语句的形式是怎么样的,如下所示: if 条件: # 代码块 elif 条件: ...

1904
来自专栏数据结构笔记

数据结构(四):栈的应用之表达式求值

用户从控制台输入一个数学表达式(所有输入均合法),数学表达式只包含四则运算,程序需输出表达式对应的结果,如:

622
来自专栏java工会

Java基础第一阶段知识点,招实习的面试官都在问这些

1979

扫码关注云+社区