指针的基本操作(10.1 Basic Pointer Operations)

[This section corresponds to K&R Sec. 5.1]

The first things to do with pointers are to declare a pointer variable, set it to point somewhere, and finally manipulate the value that it points to. A simple pointer declaration looks like this:

对指针的第一步操作就是声明一个指针变量,让它指向某个地方,最后操作指针指向的值,一个简单的指针声明如下:

	int *ip;

This declaration looks like our earlier declarations, with one obvious difference: that asterisk. The asterisk means that ip, the variable we're declaring, is not of typeint, but rather of type pointer-to-int. (Another way of looking at it is that *ip, which as we'll see is the value pointed to by ip, will be an int.)

这个声明看起来非常像我们之前的变量声明,但是有一个明显的不同之处,就是那个星号(*),帅帅的星号跟着ip,这个我们声明的ip变量,不是int类型,它是一个指向整型的指针。(用另一种方法来看这个表达式是,先看*p做一个整体,*p的类型是一个int类型,然后*p分开,把*看到是取地址符号,那ip就是一个指针,也即一个地址,*ip取这个地址的值,这个地址的值是一个int类型)

We may think of setting a pointer variable to point to another variable as a two-step process: first we generate a pointer to that other variable, then we assign this new pointer to the pointer variable. We can say (but we have to be careful when we're saying it) that a pointer variable has a value, and that its value is ``pointer to that other variable''. This will make more sense when we see how to generate pointer values.

我们会想设置一个指针指向另外一个变量要用两个步骤,首先,我们声明一个存放在其他地方的变量,然后我们把这个变量的地址赋值给这个指针。我们可以这样说(但必须注意我们的描述)指针变量保存有一个值,并且它的值是指向其他变量的。这会使得我们对如何生成一个指针变量更加直观。

Pointers (that is, pointer values) are generated with the ``address-of'' operator &, which we can also think of as the ``pointer-to'' operator. We demonstrate this by declaring (and initializing) an int variable i, and then setting ip to point to it:

Pointers这个指指针的值,通常我们会用到取地址符号(&),当然我们也可以把它认为是“pointer-to”操作。我们声明一个int变量i,然后把ip指向这个变量i.

	int i = 5;ip = &i;
The assignment expression  ip = &i;  contains both parts of the ``two-step process'':  &i  generates a pointer to  i , and the assignment operator assigns the new pointer to (that is, places it ``in'') the variable  ip . Now  ip  ``points to''  i , which we can illustrate with this picture: 

ip=&i;这个表达包含两个步骤,&i是一个指向i的指针,然后把新声明的指针ip指向这个地方,也即这个指针,这个地址。好了。现在ip就指向了i,我们可以用如下图示来表示:

i is a variable of type int, so the value in its box is a number, 5. ip is a variable of type pointer-to-int, so the ``value'' in its box is an arrow pointing at another box. Referring once again back to the ``two-step process'' for setting a pointer variable: the & operator draws us the arrowhead pointing at i's box, and the assignment operator =, with the pointer variable ip on its left, anchors the other end of the arrow in ip's box.

i是一个整型变量,所以在框框里的是一个数字5,ip是一个指向整型变量的指针,所以ip保存的值是一个地址,并且这个地址保存的是一个整型变量。重新回来看一下两步操作法:为了设置一个指针变量,&操作取得指向框框里的地址,然后是“=”操作符,把指针变量ip放在左边,最后重点是i的地址保存在了ip的框框里。

We discover the value pointed to by a pointer using the ``contents-of'' operator, *. Placed in front of a pointer, the * operator accesses the value pointed to by that pointer. In other words, if ip is a pointer, then the expression *ip gives us whatever it is that's in the variable or location pointed to by ip. For example, we could write something like

我们发现要取得指针指向的值用(*)操作符,放在指针的前面,(*)操作取得指针指向地址的值,换句话说,如果ip是一个指针,*ip表达式告诉我们ip这个地址的值保存的值是多少,例如,我们可以这样写一行代码:

	printf("%d\n", *ip);

which would print 5, since ip points to i, and i is (at the moment) 5.

当然这会打印5,由于ip指向i,i的值(此时)是5.

(You may wonder how the asterisk * can be the pointer contents-of operator when it is also the multiplication operator. There is no ambiguity here: it is the multiplication operator when it sits between two variables, and it is the contents-of operator when it sits in front of a single variable. The situation is analogous to the minus sign: between two variables or expressions it's the subtraction operator, but in front of a single operator or expression it's the negation operator. Technical terms you may hear for these distinct roles are unary and binary: a binary operator applies to two operands, usually on either side of it, while a unary operator applies to a single operand.)

你一定想知道(*)取地址值的操作,与此同时,他也是乘法操作符。在这里是没有一点模糊的,乘法操作要具有两个变量,当它作为取地址值操作符时,它放在变量的前面,它就像减号(-)一样,当它在两个变量或者堂之间时,它是减号的功能,当它在一个常量前面时,它被当作负号。这就像一个操作符具有两种功能,简单叫它作二次元吧。哈哈!

The contents-of operator * does not merely fetch values through pointers; it can also set values through pointers. We can write something like

取地址值符(*)不仅仅是取得地址的值,也可以通过这个方法来设置一个地址的值。像下面一样:

	*ip = 7;

which means ``set whatever ip points to to 7.'' Again, the * tells us to go to the location pointed to by ip, but this time, the location isn't the one to fetch from--we're on the left-hand sign of an assignment operator, so *ip tells us the location to store to. (The situation is no different from array subscripting expressions such as a[3] which we've already seen appearing on both sides of assignments.)

这是把ip指向的值设置为7.再次,(*)符号告诉我们它是取得(ip)地址的值的。但是这次,这个地址不是一个取得的值,左边的表达式(*ip)是取得ip指向的位置。(这就像数组里面的a[3]取得数组里面第2个元素的值一样)

The result of the assignment *ip = 7 is that i's value is changed to 7, and the picture changes to: 

*ip=7这个表达式的结果是把ip这个地址的值变为7.上面的图改成下面:


If we called printf("%d\n", *ip) again, it would now print 7.

我们当然可以用打印来看到*ip的值。它会打印7.

At this point, you may be wondering why we're going through this rigamarole--if we wanted to set i to 7, why didn't we do it directly? We'll begin to explore that next, but first let's notice the difference between changing a pointer (that is, changing what variable it points to) and changing the value at the location it points to. When we wrote *ip = 7, we changed the value pointed to by ip, but if we declare another variable j:

	int j = 3;
and write
	ip = &j;

we've changed ip itself. The picture now looks like this: 

指针,我们可能想知道为啥我们写这么多这么啰嗦。如果我们想把它设置成7.为什么我们不直接操作,我们下面会探讨这个,但是首先让我们注意改变指针的值和改变指向指向位置的值的不同之处。当我们写*ip=7我们是改变指针指向地址的值的。但是如果我们声明另一个变量j.

       int j=3;

然后写

       ip=&j;

我们改变了ip的值,如下图:

我自己试了一下。要这样写才会正确:如果不要int i=8;int *ip=&i;只写成int*ip;可能会造成ip指向的地方不合法,会出错。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int main(void)
{	int i=8;int *ip=&i;*ip=7;printf("%d\n",*ip);return 0;
}


We have to be careful when we say that a pointer assignment changes ``what the pointer points to.'' Our earlier assignment

我们一定要注意,当我们说一个指针指向改变的时候,“指针指向什么?”我们先前的分配是这样的。

	*ip = 7;

changed the value pointed to by ip, but this more recent assignment

改变ip指向地址的值,但是我们大多数是这样声明的。

	ip = &j;

has changed what variable ip points to. It's true that ``what ip points to'' has changed, but this time, it has changed for a different reason. Neither i (which is still 7) nor j (which is still 3) has changed. (What has changed is ip's value.) If we again call

ip=&j通过改变ip来达到改变ip指向的值。它是让ip指向的值发生了改变,但是这时,它因为另一个原因发生了改变。不是i的值让ip发生了变化,我们可以再来一次打印。

 

printf("%d\n", *ip);

this time it will print 3.

这时候它会打印出3来。

We can also assign pointer values to other pointer variables. If we declare a second pointer variable:

我们也可以把指针赋值给另一个指针

	int *ip2;

then we can say

这时我们可以这样写

	ip2 = ip;

Now ip2 points where ip does; we've essentially made a ``copy'' of the arrow: 

这时ip2指向的地方也是ip指向的地址,它本质上只是一个复制操作


Now, if we set ip to point back to i again:

现在我们把ip又改回i的地址

	ip = &i;

the two arrows point to different places: 

这时两个指针指向了不同的地方


We can now see that the two assignments

这时我们可以看到下面两个表达式

	ip2 = ip;
and
	*ip2 = *ip;

do two very different things. The first would make ip2 again point to where ip points (in other words, back to i again). The second would store, at the location pointed to by ip2, a copy of the value pointed to by ip; in other words (if ip and ip2 still point to i and j respectively) it would set j to i's value, or 7.

是两个不同的东西。第一个是把ip和ip2是同一个地址。第二种是保存的值,*ip2是ip2地址的值,*ip是ip地址的值,换言之(如果ip 和ip2仍然指向i和j),它会把i的值赋给j.

It's important to keep very clear in your mind the distinction between a pointer and what it points to. The two are like apples and oranges (or perhaps oil and water); you can't mix them. You can't ``set ip to 5'' by writing something like

在里心里,指针和指针指向的值你一定要有一个明确的区分,他们两个就像苹果和橘子一样。你一定不能混肴他。你不能把指针赋值5.像下面一样,是错误的。

	ip = 5;			/* WRONG */

5 is an integer, but ip is a pointer. You probably wanted to ``set the value pointed to by ip to 5,'' which you express by writing

5是一个整型,但是ip是一个指针,你大概像把ip指向的值设置成5.你可以这样写。

	*ip = 5;

Similarly, you can't ``see what ip is'' by writing

你也不能通过这样来查看ip的值。

	printf("%d\n", ip);	/* WRONG */

Again, ip is a pointer-to-int, but %d expects an int. To print what ip points to, use

再说一次,ip是一个指向整型的指针,但是%d期望是整型的,打针ip指向的值,通过下面的打印。

	printf("%d\n", *ip);

Finally, a few more notes about pointer declarations. The * in a pointer declaration is related to, but different from, the contents-of operator *. After we declare a pointer variable

最后,一小点笔记关于指针声明,(*)在声明指针中,但是有区别于操作指针,在我们声明指针后

	int *ip;
the expression 下面的表达式
	ip = &i

sets what ip points to (that is, which location it points to), while the expression

指导ip指向的值设置为5

	*ip = 5

sets the value of the location pointed to by ip. On the other hand, if we declare a pointer variable and include an initializer:

设置ip指向的值,另一方面,我们可以在声明的时候包含初始化指针的值。

	int *ip3 = &i;

we're setting the initial value for ip3, which is where ip3 will point, so that initial value is a pointer. (In other words, the * in the declaration int *ip3 = &i; is not the contents-of operator, it's the indicator that ip3 is a pointer.)

在这里(*)不是说取得ip3指向的值,而是告诉编译器,ip3是一个指针,然后把这个指针初始化为i的地址

If you have a pointer declaration containing an initialization, and you ever have occasion to break it up into a simple declaration and a conventional assignment, do it like this:

你有一个指针声明如下,并用第二步来对他进行初始化

	int *ip3;ip3 = &i;

Don't write

但是不可以这样写

	int *ip3;*ip3 = &i;

or you'll be trying to mix oil and water again.

否则,你又把油和水弄乱了

Also, when we write

当然我们也可以这样写。

	int *ip;

although the asterisk affects ip's type, it goes with the identifier name ip, not with the type int on the left. To declare two pointers at once, the declaration looks like

*告诉编译器,后面的变量是一个指针,我们可以像下面一样来声明两个指针

	int *ip1, *ip2;

Some people write pointer declarations like this:

一些人这样来声明一个指针。

	int* ip;

This works for one pointer, because C essentially ignores whitespace. But if you ever write

它在声明一个指针是正确的,但是C本质上忽视空格,但是你绝不能这样写

	int* ip1, ip2;		/* PROBABLY WRONG */

it will declare one pointer-to-int ip1 and one plain int ip2, which is probably not what you meant.

他会声明一个指向整型的指针,和一个整型变量ip2.当然不是你想要的意思


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/469657.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML animate()动画更改多个元素背景颜色但不同时生效问题

问题&#xff1a; 我想点击按钮时把页面中的body颜色和button中颜色【同时】改变 这个时候出现了body颜色先变化&#xff0c;而button颜色后变化&#xff0c;似乎是因为我的代码是这样有先后顺序的&#xff1a; $("html,body").animate({backgroundColor:BGC[rando…

plt.axis()用法详解

plt.axis(‘square’) 作图为正方形&#xff0c;并且x,y轴范围相同&#xff0c;即y m a x − y m i n x m a x − x m i n y_{max}-y_{min} x_{max}-x_{min}y plt.axis(‘equal’) x,y轴刻度等长 plt.axis(‘off’) 关闭坐标轴 官网上也贴出了其他的一些选项 plt.axis([a,…

struts2学习笔记之十一:struts2的类型转换器

Struts2的类型转换器如何实现Struts2的类型转换器&#xff1f;* 继承StrutsTypeConverter* 覆盖convertFromString和convertToString注册类型转换器* 局部类型转换器&#xff0c;局部类型转换器只对当前Action起作用&#xff0c;需要提供如下配置文件&#xff1a;MyActionName-…

【Pytorch神经网络基础理论篇】 01 从零开始介绍深度学习算法和代码实现

同学你好&#xff01;本文章于2021年末编写&#xff0c;已与实际存在较大的偏差&#xff01; 故在2022年末对本系列进行填充与更新&#xff0c;欢迎大家订阅最新的专栏&#xff0c;获取基于Pytorch1.10版本的理论代码(2023版)实现&#xff0c; Pytorch深度学习理论篇(2023版)…

【Pytorch神经网络基础理论篇】 02 pytorch环境的安装

同学你好&#xff01;本文章于2021年末编写&#xff0c;已与实际存在较大的偏差&#xff01; 故在2022年末对本系列进行填充与更新&#xff0c;欢迎大家订阅最新的专栏&#xff0c;获取基于Pytorch1.10版本的理论代码(2023版)实现&#xff0c; Pytorch深度学习理论篇(2023版)…

JavaScript (If...Else和Switch和循环遍历) 语句以及常用消息框

If...Else 语句 JavaScript中if...else语句和Java中的语法和使用方法是一样的。 只是在JavaScript中要使用小写字母。使用大写的 IF 会出错&#xff01; 至于if...else...else if...和Java中的都是一样的。 例&#xff1a; var d new Date() var time d.getHours()if (time&l…

numpy中两个array数值比较,在IDE中显示完全相同,但是bool判断两个array是否相等却返回False

numpy踩坑&#xff1a;两个array中数值分别比较&#xff0c;在IDE显示相同&#xff0c;但是bool判断两个array是否相等值却是False 在numpy数据比较时&#xff0c;在IDE显示完全相同但是比较是否相等却有时候返回False&#xff1f; 原因出在了精度显示上面&#xff0c;在代码开…

C两个小例子(数组与指针)

大端模式 所谓的大端模式&#xff0c;是指数据的高位&#xff0c;保存在内存的低地址中&#xff0c;而数据的低位&#xff0c;保存在内存的高地址中&#xff0c;这样的存储模式有点儿类似于把数据当作字符串顺序处理&#xff1a;地址由小向大增加&#xff0c;而数据从高位往低位…

智慧交通day03-车道线检测实现03:相机校正和图像校正的实现

1.相机标定 根据张正友校正算法&#xff0c;利用棋盘格数据校正对车载相机进行校正&#xff0c;计算其内参矩阵&#xff0c;外参矩阵和畸变系数。 标定的流程是&#xff1a; 准备棋盘格数据&#xff0c;即用于标定的图片对每一张图片提取角点信息在棋盘上绘制提取到的角点&a…

win10编辑js文件报错,错误','

在filezilla中编辑js文件报错&#xff0c;在本地可以使用文本编辑&#xff0c;但需重新上传覆盖&#xff0c;很不方便 在win10默认应用中修改为文本编辑即可&#xff0c;在FTP编辑&#xff1a; 直接可以打开编辑

智慧交通day03-车道线检测实现04:车道线提取原理+代码实现+效果图

我们基于图像的梯度和颜色特征&#xff0c;定位车道线的位置。 在这里选用Sobel边缘提取算法&#xff0c;Sobel相比于Canny的优秀之处在于&#xff0c;它可以选择横向或纵向的边缘进行提取。从车道的拍摄图像可以看出&#xff0c;我们关心的正是车道线在横向上的边缘突变。Ope…

宝塔+wordpress搭建/迁移网站

使用宝塔linux和阿里云ECS搭建网站/从百度云服务器迁移网站到阿里云ECS 为服务器安装宝塔软件 示例&#xff1a; ECS:Ubuntu 18.04 打开阿里云控制台&#xff0c;进入已绑定的实例页面&#xff0c;使用workbench或者VNC&#xff08;推荐使用workbench&#xff0c;workbench可…

智慧交通day03-车道线检测实现05:透视变换+代码实现

为了方便后续的直方图滑窗对车道线进行准确的定位&#xff0c;我们在这里利用透视变换将图像转换成俯视图&#xff0c;也可将俯视图恢复成原有的图像&#xff0c;代码如下&#xff1a; 计算透视变换所需的参数矩阵&#xff1a; def cal_perspective_params(img, points):offs…

李宏毅老师ML_HW1——PM2.5预测

处理数据之前的pre-process 观察下载的数据文件train.csv train.csv只有每个月前20天的数据&#xff0c;另外每个月剩下10天数据用于作业结果评估&#xff0c;对学生不可见 观察数据发现rainfall栏有很多NR表示没有降雨&#xff0c;但是我们只需要数字&#xff0c;因此可以使用…

“员工请假”流程及在线表单开发示例

1. “员工请假”流程及在线表单开发示例 1.1. 描述 通过本示例达到快速对F2流程管理平台的在线表单速讯上手及零编码式的开发。实现一个以请假为示例的流程及在线表单&#xff0c;及请假数据的查询。 1.2. 目标效果 &#xff08;1&#xff09; 如何配置一个“请假在线表单” &a…

【Pytorch神经网络基础理论篇】 03 数据操作 + 数据预处理

同学你好&#xff01;本文章于2021年末编写&#xff0c;已与实际存在较大的偏差&#xff01; 故在2022年末对本系列进行填充与更新&#xff0c;欢迎大家订阅最新的专栏&#xff0c;获取基于Pytorch1.10版本的理论代码(2023版)实现&#xff0c; Pytorch深度学习理论篇(2023版)…

git版本控制系统常用指令,Xmind笔记整理

git仓库使用、项目版本管理基本常用指令 纯手工整理Xmind笔记&#xff1a; 点我下载 预览图&#xff1a; Png&#xff1a; 如有错误&#xff0c;谢谢指出

Spark学习(一) -- Spark安装及简介

标签&#xff08;空格分隔&#xff09;&#xff1a; Spark 学习中的知识点&#xff1a;函数式编程、泛型编程、面向对象、并行编程。 任何工具的产生都会涉及这几个问题&#xff1a; 现实问题是什么&#xff1f;理论模型的提出。工程实现。思考&#xff1a; 数据规模达到一台机…

Django基本概念、安装、配置到实现框架,Xmind学习笔记

Django从安装、配置到实现简单web框架的基本操作流程 纯手工Xmind笔记整理&#xff1a; 点我下载 预览图&#xff1a; 如有错误&#xff0c;谢谢指出

智慧交通day03-车道线检测实现06:车道线定位及拟合+代码实现

学习目标 了解直方图确定车道线位置的思想我们根据前面检测出的车道线信息&#xff0c;利用直方图和滑动窗口的方法&#xff0c;精确定位车道线&#xff0c;并进行拟合。 1. 定位思想 下图是我们检测到的车道线结果&#xff1a; 沿x轴方向统计每一列中白色像素点的个数&…