一维数组与指针
专题7 数组和指针的应用

例1. 写出结果: main() { int *p1, a[10]={1,2,3,4,5,6,7,8,9,10} ; p1=a; printf(“%d ”,*p1); printf(“%d ”,*p1++); printf(“%d ”, *(p1+3)); printf(“%d ”,*++p1); printf(“%d ”,(*p1)++); printf(“%d ”,*p1--); printf(“%d ”,*p1); } 例2.若有定义语句:double x[5]={1.0,2.0,3.0,4.0,5.0},*p=x;则错误引用x数 组元素的是[08年9月] A)*p B)x[5] C)*(p+1) D)*x
[C] D) aa+1
(3)通过指针变量来表示数组中各元素的地址
可以定义一个指针变量来存放数组的指针或数组元素的指针,且指针变 量的基类型就是定义数组时的类型 int *p,a[10]; for(p=a,k=0; k<10;k++) p++; 将数据写入数组元素中几种方式: (1)for(p=a,k=0; k<10;k++) { scanf(“%d”,p); p++; } 进一步简化: (2)for(p=a,k=0; k<10;k++) scanf(“%d”,p++); 再进一步简化: (3)for(p=a,p-a<10; p++) scanf(“%d”,p); 以上三种写法是等价的,要掌握,能看懂。
2、 通过指针变量来引用一维数组元素 当指针变量指向数组中的某个数组元素时,可以通过“*”来访问其所 指向变量的数据。
C语言数组参数与指针参数

C语言数组参数与指针参数我们都知道参数分为形参和实参。
形参是指声明或定义函数时的参数,而实参是在调用函数时主调函数传递过来的实际值。
一、一维数组参数1、能否向函数传递一个数组?看例子:void fun(char a[10]){char c = a[3];}intmain(){char b[10] = “abcdefg”;fun(b[10]);return 0;}先看上面的调用,fun(b[10]);将b[10]这个数组传递到fun 函数。
但这样正确吗?b[10]是代表一个数组吗?显然不是,我们知道b[0]代表是数组的一个元素,那b[10]又何尝不是呢?只不过这里数组越界了,这个b[10]并不存在。
但在编译阶段,编译器并不会真正计算b[10]的地址并取值,所以在编译的时候编译器并不认为这样有错误。
虽然没有错误,但是编译器仍然给出了两个警告:warning C4047: 'function' : 'char *' differs in levels of indirection from 'char 'warning C4024: 'fun' : different types for formal and actual parameter 1这是什么意思呢?这两个警告告诉我们,函数参数需要的是一个char*类型的参数,而实际参数为char 类型,不匹配。
虽然编译器没有给出错误,但是这样运行肯定会有问题。
如图:这是一个内存异常,我们分析分析其原因。
其实这里至少有两个严重的错误。
第一:b[10]并不存在,在编译的时候由于没有去实际地址取值,所以没有出错,但是在运行时,将计算b[10]的实际地址,并且取值。
这时候发生越界错误。
第二:编译器的警告已经告诉我们编译器需要的是一个char*类型的参数,而传递过去的是一个char 类型的参数,这时候fun 函数会将传入的char 类型的数据当地址处理,同样会发生错误。
C语言中数组的总结

C语言中数组的总结目录1.数组的定义2.一维数组的创建和初始化3.给数组元素赋值4.数组下标越界5.二维数组6.多维数组7.指针与一维数组8.指针与多维数组9.指针,数组与函数10.变长数组11.以上全部内容数组的定义1.数组:一系列相同数据类型的有序序列。
2.声明数组:int states[50];char code[28];float candy[13]; 等等……通过声明将会告知编译器三个信息:1)数组内含有多少元素2)元素的数据类型3)数组名一维数组的创建和初始化1.数组的初始化:在数组创建时,我们要为数组初始化。
int months[12]={31,28,31,30,31,30,31,31,30,31,30,31};//数组的初始化int months[ ]={ 31,28,31,30,31,30,31,31,30};//初始化时省略方括号中的数字,编译器会根据初始化列表中项数来确定数组的大小。
(本例中数组的大小为9)const int months[12]={31,28,31,30,31,30,31,31,30,31,30,31};//将数组设置为只读,这样程序只能从数组中检索值,不能把新值写入数组。
(一旦声明为const,便不能再给他赋值)以花括号括起来,用逗号分隔数组元素来初始化数组,逗号和值之间可以使用空格。
C const 与C++ const区别一:c++允许在声明数组时使用const整数变量,而c不允许。
区别二:const定义的变量未初始化时,c会使用一个变量地址上的随机的值,c++会报错未初始化的const 'y'。
区别三:const int y;const int *p2 =&y;int * p1;p1 = p2;//c++不允许这么做(从'const int*'到'int*' [- fper]的无效转换),c 会给出一个警告(赋值从指针目标类型中丢弃“const”限定符)1)失败的初始化数组a)未初始化数组:数组元素和未初始化的普通变量一样,编译器使用的值是内存地址上现有的值,使得数组储存的都是垃圾值。
[工学]《C语言程序设计》第5章___数组、字符串、指针
![[工学]《C语言程序设计》第5章___数组、字符串、指针](https://img.taocdn.com/s3/m/c07859c84afe04a1b071de5c.png)
5.2.2 一维数组的初始化
1、数组声明时初始化 在编译阶段进行的。这样将减少运行时间, 提高效率。 数组初始化的一般形式为: 类型符 数组名[常量表达式]={值,值…值}; 例如: int a[10]={ 0,1,2,3,4,5,6,7,8,9 }; 相当于a[0]=0; a[1]=1;... a[9]=9;
…
a[9]
#include <stdio.h> 声明有10个元素 void main() 的一维数组a {int n,i; float s=0, ave, a[10]; a[0] a[1] … a[9] for(i=0;i<10;i++) a[i] { scanf("%f",&a[i]); a[i] s=s+a[i]; } ave=s/10; for(i=0;i<10;i++) a[i] a[i] if (a[i]>ave) printf("%f ",a[i]); }
说明: ① int a[10]={0,1,2,3,4};
给前5个元素赋 值,其余赋0值 不能给数组整体 赋值,改成{1} 静态存储类型, 初值为0 可以省略数组元 素个数。 初值的个数不能 超过元素个数
② int a[10]=1;
③ static int a[3]; ④ int a[ ]={1,2,3,4,5}; ⑤ int a[5]={1,2,3,4,5,1 };
代码: for(i=0; i<N-1; i<5; i++) { p=i; for(j=i+1; i<N; j<6; j++) if(a[j]<a[p]) p=j; t=a[i]; a[i]=a[p]; a[p]=t; } 5-5.c
数组与指针

此外,还可通过算术元运算对指针进行移动, 此外,还可通过算术元运算对指针进行移动,来达到引用 其他数组元素的目的。 其他数组元素的目的。 a[0] p p &a[0] *p a[0] a[1] p+1 p+1 &a[1] *(p+1) a[1] a[2] P+2 p+2 &a[2] *(p+2) a[2] a[3] P+3 p+3 &a[3] *(p+3) a[3] a[4] p+4 p+4 &a[4] *(p+4) a[4]
a[0] a[1] a[2] a[3] a[4]
a
a a+1 a+2 a+3 a+4
a a+1 a+2 a+3 a+4
&a[0] &a[1] &a[2] &a[3] &a[4]
*a *(a+1) *(a+2) *(a+3) *(a+4)
a[0] a[1] a[2] a[3] a[4]
例3: main() { int a[5],*p,i; for(i=0;i<5;i++) scanf(“%d”,a+i); for(i=0;i<5;i++) printf(“%d”,*(a+i)); }
a[1] a[1][0] a[1][1] a[1][2]
此处, 的值与 的值与a[0]的值相同,但是基类型不同。a是二级 的值相同, 此处,a的值与 的值相同 但是基类型不同。 是二级 指针, 是一级指针。 指针,a[0]是一级指针。 是一级指针 a &a[0][0] a[0] 因此,以下赋值语句是错误的: 因此,以下赋值语句是错误的:p=a; a &a[0] a+1 &a[1] a+i &a[i] *(a+i) a[i]
指针和一维数组经典题目

指针和一维数组经典题目
下面是一些经典的指针和一维数组题目:
1. 求一个一维数组的和、平均值、最大值、最小值。
2. 将一个一维数组元素逆序存放。
3. 合并两个有序的一维数组为一个新的有序数组。
4. 将一个一维数组中的奇数和偶数分别放在两个新的一维数组中。
5. 给定一个一维数组和一个目标值,判断目标值是否存在于数组中。
6. 给定一个一维数组和一个目标值,查找目标值在数组中的索引。
7. 统计一个一维数组中0的个数。
8. 对一个一维数组进行冒泡排序或选择排序。
9. 将一个一维数组循环右移k位。
10. 判断一个一维数组是否为回文数组。
这些题目可以帮助您巩固指针和一维数组的基本操作,同时也可以提高您的编程能力。
C++程序设计教程-第4章 数组和指针-106

4.2
对一维数组而言,数组名和指针有许多相 通的地方,归纳如下:
(1) 数组名a表示数组的起始地址。可以利 用a+i表示的第i+1个元素的地址,即&a[i];
(2) 将指针变量pInt指向数组a的起始地址 的方法有两种,即pInt=a或pInt=&a[0];
(2) 第二种方法是通过强制类型转换用一 个整型常数直接初始化指针类型的变量。这 种方法必须在清楚目前存储空间那些“空闲 ”的前提下才能使用,否则在程序运行过程 中将会出现致命错误。
4.2
指针变量的值始终是一个地址,它是一个 无符号整型数据。
指针变量所指向的数据的类型与指针的 类型一致,它的值可以用如下的方法获得:
*<指针变量>
这里的运算符“*”称为取内容运算符。该
运算符的运算结果为作为其操作数的指针变 量所指向的数据的值。
4.2
二、指针变量的操作 1、指针变量的赋值运算 (1) 将一个变量的地址直接赋给同类型的 指针变量。
(2)同类型的指针之间可以互相赋值,此 时这两个指针指向同一个内存单元。
(3)不同类型的指针变量之间可以通过类型 强制转换互相赋值。但这样的赋值通常没有 价值。
用的空间,由于它存放的是地址,因此该空
间通常与int类型的数据所占用的空间相同,
为4个字节;另一个为该指针变量所指向的数
据所占用的存储空间。如图下图所示(以字
符型指针ptrch1为例):
ptrch1:
20001
ptrch1所指向的数据:
地址为20001
4.2
指针变量的初始化方法有两种:
c语言5

5.1.3 与指针有关的运算
例5-2 分析下列程序的输出结果。
#include <stdio.h> void main( ) { char a[5]="1234"; char *p; p=a; /*指针变量p指向数组的第一个元素a[0]*/ printf("%d\n",*p); /*输出第一个元素的ASCII值*/ p++; /*指针变量p指向数组的第二个元素a[1]*/ printf("%d\n",*p); /*输出第二个元素的ASCII值*/ }
指针是一种数据类型。 指针是指存放数据的 内存地址 。程序中定义的 变量、数组都要分配内存空间,通过这些空间的地 址可以访问存储在其中的数据,也就是引用变量或 数组元素。可以看出,指针提供了访问数据的另一 种方法(通过变量名访问数据是一种)。
5.1.1 指针的概念
“指针”是个地址概念,是指内存储器中存储单元的地 址。变量在内存中使用存储空间的起始地址,称为该变量 的指针,如图所示。
又:一维数组元素的指针法引用 *(x+i) 与 x[i]等价, 所以,二维数组元素的指针引用法形式为: *(*(x+i)+j) 例5-5 使用指针的方法,输出二维数组的元素。 void main() { int x[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; int i,j; for(i=0;i<3;i++) { for(j=0;j<4;j++) printf("%5d",*(*(x+i)+j)); printf("\n"); } }
5.1.3 与指针有关的运算
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
指 针
1、 概述
1.1 地址和指针的概念
如果在C 语言中定义一个变量,系统会自动的给它存储空间。
比如:int a,b,c;系统会自动的给a,b,c 分别分配2个字节的空间,内存中的表示如下图:
这样以来,就建立了变量和地址的对应关系。
如果产生赋值行为,比如:a=1,b=3;,存储图如下:
如果产生具体的操作,比如:c=a+b ,具体的过程如下: 第一步:从2001-2002字节空间取出1; 第二步:从2003-2004字节空间中取出3;
第三步:将1和3相加后的结果4存入变量C 所指向的地址空间(2005-2006),图例如下:
a
b c
a
b c
以上的程序,在C 语言中称为“直接访问”。
既然有“直接访问”,肯定会存在“间接访问”,举例如下:
张三出差,住宾馆,房间号码为1001,从携带钥匙的方式上来看,有两种方式: 1、 钥匙自己带(直接方式);
2、 钥匙放在总台上,要开门,先到总台拿钥匙,而后开门(间接方式) 以上是生活中的例子,那么,在C 程序中,如何表示这种“间接方式”呢? 第一步:定义一个普通的变量并赋值(int a=3;)
第二步:定义一种变量,用来存储变量a 的地址(a_pointer );
第三步:建立该变量和普通变量之间的联系,将变量a 的地址存储到a_pointer 中。
第四步:通过该变量(a_pointer )来访问a;
程序如下:
b c
一种示意图:
以上的图形象的表示了一种“指向关系”。
“*”,表示指向。
在C 语言中,一个变量的地址被称为该变量的“指针”,存储该变量地址的“东东”,称为指针变量。
故,指针是一个地址,而指针变量是存放该地址的变量,它用来指向“指针”所表示的地址。
1.2 指针变量的定义和使用
定义格式:
数据类型(基本型) *指针变量
比如:int *pointer_1;指针变量是pointer_1,而不是*pointer_1; 有了以上的定义,pointer_1是我们定义的指针变量,*pointer_1是具体的内容。
从以上程序来看,*pointer_1和i 是一回事。
到此为止,我们已经知道了指针变量的定义,既然变量定义了,就要使用,如何使用呢?
要想使用,必须理解连个运算符号:
●&:取地址运算符
●*:指针运算(也称为“间接访问”运算符),取其指向的内容。
在指针定义和使用过程中的注意点:
通过以上的学习,我们的感觉:真烦!!!当时,随着学习的深入,我们会逐步体会到指针的好处:
●可以使程序简洁、紧凑、高效
●在函数调用后改变有关变量的值
●高效的处理数组和字符串
●动态分配内存
●直接处理地址
●有效的表示复杂的数据结构
●完成文件的操作
1.3 指针变量作为函数的参数
2、数组与指针
2.1 一维数组与指针
在前面的学习过程中,我们再三提到一个概念:数组名代表数组的首地址,比如: Int a[5]={12,34,56,78,11};
数组的数据在内存中的存储结构如下:
有了这张图以后,我们隆重推出一个重要的概念:a=&a[0]
如果我们定义了一个指针变量,并让其和数组a 建立联系,程序如下:
既然数组和指针建立了联系,该如何使用数组呢?
数组的使用,除了前面学过的使用下表法以外,只要数组和指针建立了联系,就可以通过指针的操作来使用数组。
a=&a[0]
a[0] a[1] a[2] a[3] a[4]
C语言规定:
●如果指针变量p指向数组中的一个元素,则p+1指向数组的下一个元素,p-1指向
数组的上一个元素。
●同理,根据p=a,则a+1指向数组的下一个元素,a-1指向数组的上一个元素。
下面,通过例子来说明:
例子:设有一个一维整形数组,有10个元素,请输出全部的原素。
【方法三】指针法:
在以上程序编写方法中:
1、下标法比较直观(大家喜欢);
2、以上三种方法中,方法三的执行效率最高,在方法三中,方法二执行效率最高。
3、注意p是变量,p++、p+=1都是成立的;a是常量,a++(--) 、a+=1是万万不行
的。
特别提醒各位的是,指针在“指来指去”的过程中,当前值是变化的。
对此,有可能造成程序的混乱。
例子:输入5个整数给整形数组,然后输出。
以上的程序看起来没有说明错误,但运行结果却是错的,为什么?
原因:经过第一个循环后,指针变量p中存储的已经不是&a[0]了,而是指向了数组的尾端,即p+5,其值不可预料,C在编译的时候不会提示错误,这对于初学者来说,很难发现,提醒大家注意。
2.2 一维数组作为函数的参数
以上的表,可以形成4种组合:
例子:编一个函数,求一数组中最小的元素。
【组合一】实参和形参均为数组名
实战训练
1、输入三个整数,按从大到小的顺序输出(用指针的方法)
2、通过指针操作,找出三个整数中的最小值并输出。
3、调用自定义的函数getint()读入以正整数,并将其输出(读程序,分析程序)。