数组和指针的区别
- 格式:ppt
- 大小:1.74 MB
- 文档页数:10
指针和数组的关系
指针和数组是C语言中非常重要的概念,理解它们对于编写高效程序和避免常见错误
至关重要。
指针和数组的关系可以说是紧密相连的,因为数组名本质上就是一个指针。
在C语言中,数组名表示一个指向该数组第一个元素的指针,也就是数组的起始地址。
因此,如果我们定义一个数组a,那么&a和a是等价的,都表示数组第一个元素的地址。
例如,定义一个整型数组a:
int a[5] = {1, 2, 3, 4, 5};
我们可以通过数组名a访问数组中的元素。
例如,a[0]表示数组中的第一个元素,即1。
在C语言中,数组名本身是一个常量,即不能对其进行修改。
但是,我们可以使用指
针来访问数组中的元素,这就需要对指针进行加减运算来实现。
我们可以定义一个指向数组a的指针p,然后通过指针访问数组中的元素。
例如,*p
表示指针p所指向的数组的第一个元素,即1。
我们可以通过p++将指针p指向数组中的下一个元素,例如*p++表示指向数组中的第二个元素,即2。
因此,数组名和指针在C语言中是紧密相关的,数组名本质上就是一个指向数组第一
个元素的指针。
我们可以通过指针访问数组中的元素,并通过加减运算实现对数组的遍
历。
在实际编程中,使用指针可以提高程序的效率和灵活性。
使用指针可以避免对数组名
的重复引用,从而减少程序的存储空间和运行时间开销。
但是,指针操作也比较容易出现指针越界、空指针等错误,因此在使用指针时需特别
注意,避免出现不必要的错误。
数组和指针的区别数组和指针是C语言中非常重要的两个概念,它们在编写程序时起着极其重要的作用。
虽然它们在某种程度上非常相似,但它们之间也存在着很多的差异,下面我们就来分析一下它们的区别。
1. 定义方式数组是由一组具有相同类型的数据元素所组成的有序集合,每个元素具有相同的数据类型,可以通过下标在数组中访问对应的元素。
在C中,定义一个数组可以使用以下语句:```int arr[10];```这个语句定义了一个名为arr的整型数组,这个数组有10个元素。
而指针是一个变量,它存放了一个内存地址,这个地址与它存储的数据类型有关。
在C中,定义一个指针可以使用以下语句:```int *p;```这个语句定义了一个名为p的指针,这个指针指向一个整型变量。
2. 内存分配数组在定义时要求需要一定的内存空间来存储数组元素,因此在定义时就已经确定了内存空间的大小,且数组的大小不可改变。
例如,如果定义一个大小为10的数组,则它的大小就是10,无论实际使用时需要存储的元素个数是多少,数组的大小都不会改变。
而指针在定义时只需要分配一个指针变量所需的内存空间,该指针可以在程序运行时动态地分配内存,因此指针所指向的内存空间大小不确定,需要在运行时根据需要动态地分配或释放空间。
3. 访问方式在数组中,可以通过数组的下标来访问数组中具体的元素,下标从0开始,最大下标为数组大小减1。
例如,访问arr数组中的第三个元素可以写成:arr[2]。
而对于指针,可以通过指针变量所指向的地址来访问该地址所对应的值。
例如,访问p指针所指向地址上的整型变量可以写成:*p。
4. 传递方式在函数调用时,数组可以通过值传递或指针传递来传递数组的值。
如果数组作为参数传递给函数时,实际上传递的是该数组的地址,即使数组非常大,也不会导致栈溢出。
而对于指针,只能通过指针传递方式来传递指针变量的值,在函数内部可以通过指针来修改该指针所指向的地址所存储的值,因此指针可以用来传递地址或修改变量的值。
用指针访问数组的方法一、指针与数组的关系。
1.1 指针就像是数组的导航员。
数组在内存里是一块连续的空间,就像住在公寓里的一排房间。
而指针呢,就好比是房间的钥匙或者说是指向这些房间的路标。
它能准确地找到数组里的每个元素,这就跟你拿着钥匙能打开对应的房间门一样。
咱们可以把数组想象成一群小伙伴排着队,指针就可以指出哪个是排头,哪个是排尾,还能找到中间的小伙伴。
1.2 从本质上来说,数组名其实就是一个指针常量。
这就像是一个固定的地址标签,它指向数组的第一个元素。
就好比你家的门牌号,永远指着你家这个“元素”所在的位置。
而且,这个指针常量是不能被修改的,就像你不能随便更改你家的门牌号一样。
二、用指针访问数组元素。
2.1 简单的访问方式。
咱们先定义一个数组,比如说int arr[5] = {1, 2, 3, 4, 5};再定义一个指针,int p = arr; 这里的arr就相当于把数组的首地址给了指针p。
现在如果我们想访问数组的第一个元素,就可以用p,这就像是通过钥匙打开了第一个房间。
如果我们想访问第二个元素呢,那就可以让指针p指向下一个元素,也就是p++,然后再用p来获取这个元素的值。
这就好像你沿着走廊走到下一个房间,再用钥匙打开门看看里面有啥。
2.2 灵活的遍历。
通过指针来遍历数组那是相当方便的。
我们可以写一个简单的循环,像这样:for (int p = arr; p < arr + 5; p++) { printf("%d ", p); }。
这个循环就像是一个小机器人,从数组的开头沿着指针这个“导航路线”一直走到结尾,把每个房间里的东西(元素的值)都展示出来。
这就好比是你沿着一排房间一个一个地查看里面的情况,一个都不落下。
2.3 指针运算的妙处。
指针的运算在访问数组的时候可是很有讲究的。
比如说,p + 2,这里可不是简单的数学加法,它实际上是让指针向后移动两个元素的位置。
这就像是你一下子跳过两个房间,直接到第三个房间的门口。
字符串指针与字符数组的区别(转载)用字符数组和字符指针变量都可实现字符串的存储和运算。
但是两者是有区别的。
在使用时应注意以下几个问题:1. 字符串指针变量本身是一个变量,用于存放字符串的首地址。
而字符串本身是存放在以该首地址为首的一块连续的内存空间中并以‘\0’作为串的结束。
字符数组是由于若干个数组元素组成的,它可用来存放整个字符串。
2. 对字符串指针方式char *ps="C Language";可以写为:char *ps;ps="C Language";而对数组方式:static char st[]={"C Language"};不能写为:char st[20];st={"C Language"};而只能对字符数组的各元素逐个赋值。
从以上几点可以看出字符串指针变量与字符数组在使用时的区别,同时也可看出使用指针变量更加方便。
当一个指针变量在未取得确定地址前使用是危险的,容易引起错误。
一个错误的例子,如下:char *name;scanf("%s",name);printf("%s",name);有的编译器虽然也能通过,但这是错误的,因为是个指针,定义时指向不可用的地址。
解决这个问题有两种方法:用数组的方法或给字符针针分配内存空间的方法。
数组的方法:char name[20];scanf("%s",name);printf("%s",name);给字符针针分配内存空间的办法:char *name;name=(char*)malloc(50);//此时name已经指向一个刚刚分配的地址空间。
scanf("%s",name);printf("%s",name);但是对指针变量直接赋值是可以的。
因为C系统对指针变量赋值时要给以确定的地址。
理解C语⾔(⼀)数组、函数与指针1 指针⼀般地,计算机内存的每个位置都由⼀个地址标识,在C语⾔中我们⽤指针表⽰内存地址。
指针变量的值实际上就是内存地址,⽽指针变量所指向的内容则是该内存地址存储的内容,这是通过解引⽤指针获得。
声明⼀个指针变量并不会⾃动分配任何内存。
在对指针进⾏间接访问前,指针必须初始化: 要么指向它现有的内存,要么给它分配动态内存。
对未初始化的指针变量执⾏解引⽤操作是⾮法的,⽽且这种错误常常难以检测,其结果往往是⼀个不相关的值被修改,并且这种错误很难调试,因⽽我们需要明确强调: 未初始化的指针是⽆效的,直到该指针赋值后,才可使⽤它。
int *a;*a=12; //只是声明了变量a,但从未对它初始化,因⽽我们没办法预测值12将存储在什么地⽅int *d=0; //这是可以的,0可以视作为零值int b=12;int *c=&b;另外C标准定义了NULL指针,它作为⼀个特殊的指针常量,表⽰不指向任何位置,因⽽对⼀个NULL指针进⾏解引⽤操作同样也是⾮法的。
因⽽在对指针进⾏解引⽤操作的所有情形前,如常规赋值、指针作为函数的参数,⾸先必须检查指针的合法性- ⾮NULL指针。
解引⽤NULL指针操作的后果因编译器⽽异,两个常见的后果分别是返回置0的值及终⽌程序。
总结下来,不论你的机器对解引⽤NULL指针这种⾏为作何反应,对所有的指针变量进⾏显式的初始化是种好做法。
如果知道指针被初始化为什么地址,就该把它初始化为该地址,否则初始化为NULL在所有指针解引⽤操作前都要对其进⾏合法性检查,判断是否为NULL指针,这是⼀种良好安全的编程风格1.1 指针运算基础在指针值上可以进⾏有限的算术运算和关系运算。
合法的运算具体包括以下⼏种: 指针与整数的加减(包括指针的⾃增和⾃减)、同类型指针间的⽐较、同类型的指针相减。
例如⼀个指针加上或减去⼀个整型值,⽐较两指针是否相等或不相等,但是这两种运算只有作⽤于同⼀个数组中才可以预测。
最近工作之余,发现了两个自己在C语言学习中的难点,一个是字符串指针和字符数组的区别,一个就是静态全局变量、静态局部变量、全局变量和局部变量的区别,在网上查了不少资料,收获良多,现在与大家分享,有错误的地方请大家指正!以下程序用VC++6.0调试先说说字符串指针和字符数组的区别1.相同点:/* 用字符数组实现字符串操作*/main( ){char str[]="Welcome to study C !";int i;printf("%s\n",str);for (i=0;i<=7;i++)printf("%c",str[i]); //用*(str+i)也行printf("\n");}/* 用字符指针实现字符串操作*/main(){char *str="Welcome to study C !";int i;printf("%s\n",str);for(i=0;i<=7;i++)printf("%c",*(str+i)); //用str[i]也行printf("\n");}2.不同点:a)赋值方式不同,字符数组只能对各个元素分别赋值,而字符指针只需赋给字符串的首地址就可以了。
如: char *str;str="Welcome to study C !";以下对字符数组的赋值是错误的:char str[80];str[ ]="Welcome to study C !";b)字符指针指向字符串,"hello"是一个字符串常量,与之相关联的内存空间位于内存的只读部分,如:char ch[] = "china\n";char *p;char *pp = "CHINA\n";p = ch;*(p+2) = 'h';//就是可以的*(pp+2) = 'h';//此处在编译时不会出错,在执行的时候会出错c) 函数参数列表中的以数组类型书写的形式参数,编译器把其解释为普通的指针类型,对于void func (char sa[100],int ia[20],char *p),则sa的类型为char*,而不是char[100]类型下面介绍一下字符串常量和字符串变量:1.字符串常量:a)定义:是一对双引号括起来的字符序列b)字符串包含的字符个数:不包括系统自动赋的’\0’,转义字符算1个c)所占的字节数:字符串所包含的字符个数加1d)长度:从第一个字符到第一个’\0’之间的字符个数,哪怕’\0’就在原字符串中e)无论字符串常量还是字符串变量,空字符串可以存在””,而空字符是错误的’’2.字符串变量:a)C语言本身没有设置一种类型来定义字符串变量,字符串的存储完全依赖于字符数组,但字符数组又不等于是字符串变量,例如:Char str[] = {‘a’,’b’,’c’,’\0’};是str[4],是字符串Char str[] = {‘a’,’b’,’c’};是str[3],是字符数组Char str[7] = “string!”;可能破坏其他数据b)在scanf,printf,gets,puts中的str不用写成str[10],只能写成str下面介绍下静态全局变量,静态局部变量,全局变量,局部变量的区别1.从作用域看:全局变量具有全局作用域。
CC++常见问题汇总问题1、数组和指针的区别数组名不可以作为左值char * p1 = "Hello World" ; //分配字符串常量,然后赋给 p1 ,⼀个指针型变量,是左值char p2[ 20] = "Hello World" ; //分配⼀个数组,然后初始化为字符串,相当于⼀个常量,类型为数组,不是左值*p1 = 'h' ; //p1可以指向别的地⽅,但hello world不能更改p2[ 0] = 'h' ; //p2不能指向别的地⽅,但hello world可以更改si z eo f运算sizeof(指针变量p1)是编译器分配给指针(也就是⼀个地址)的内存空间。
sizeof(数组指针常量p2)是整个数组占⽤空间的⼤⼩。
但当数组作为函数参数进⾏传递时,数组就⾃动退化为同类型的指针。
取地址&运算对数组名取地址&运算,得到的还是数组第⼀个元素的地址对指针取地址&运算,得到的是指针所在的地址,也就是指向这个指针的指针。
因此main函数的参数char *argv[],也可以写成char **argv。
参考问题2、指针数组、数组指针与⼆维数组剖析定义指针数组:⾸先它是⼀个数组,数组的元素都是指针,数组占多少个字节由数组本⾝决定。
它是“储存指针的数组”的简称。
数组指针:⾸先它是⼀个指针,它指向⼀个数组。
在32 位系统下永远是占4 个字节,⾄于它指向的数组占多少字节,不知道。
它是“指向数组的指针”的简称。
实例区分int *p1[10]; //p1 是数组名,其包含10 个指向int 类型数据的指针,即指针数组int (*p2)[10]; //p2 是⼀个指针,它指向⼀个包含10 个int 类型数据的数组,即数组指针cout<<sizeof(a)<<""<<sizeof(b); //4 40实例分析符号优先级:()> [ ] > *p1 先与“[]”结合,构成⼀个数组的定义,数组名为p1,int *修饰的是数组的内容,即数组的每个元素。