C语言中,指针和数组的区别和联系?
区别:C语言把内存划分成四个区,它把一般的变量和数组等存在于内存中的栈区,所以数组在C语言的定义中只是一组同类型的普通变量,即使这个变量有可能是指针。所以他的作用比指针小的很多,而指针可以指向任何区的任何数据,所以就会觉得指针和数组名很像,但是必须要注意的是,数组名只是指针中的一种,它是指针中只指向栈区的且指针的移动范围是有限的,即数组长度。而且数组在定义之初就已经有了自己的内存,一般的指针如果未指向某一个内存块时,它是没有自己的内存的,即所谓的野指针。
联系:如上面所说,数组只是定义在栈区的一个连续变量,它的首地址就是一个指针。
总结:不仅数组有指针,所有变量都有指针,指针说白了就是内存中的地址,就像一个房间必须有一个房间号。在C/C++语言中定义一个指针,就是在栈区开辟一个内存空间用来存放它指向的内存地址,然后给指针赋值,就是把地址值赋值给刚才开辟的内存空间,然后通过访问该内存中的地址值来间接访问该地址下存放的数据。如果该地址值指向的是一块静态存储区,如字符串常量等,当然就不可以修改指向的内容啦。
经验之谈,楼楼加分啊
指针与数组的关系是什么啊
1、指针:系统为某一个变量开辟单元格,指针便指向此单元格的变量值。2、数组:系统为某一组数开辟一组单元格,数组首地址便是你定义的数组变量名。数组和指针的唯一区别是,不能改变数组名称指向的地址。对于数组来说,数组的首地址,也可以用指针来表示操作,如:int a[10];int *p,n;p = a;对第一个元素取值,可以用几种方法:n =a[0];n = *p;n = p[0];n = *(p+0) ;但是以下语句则是非法的:readings = totals; // 非法!不能改变 readings totals = dptr; // 非法!不能改变 totals数组名称是指针常量。不能让它们指向除了它们所代表的数组之外的任何东西。扩展资料下面的程序定义了一个 double 数组和一个 double 指针,该指针分配了数组的起始地址。随后,不仅指针符号可以与数组名称一起使用,而且下标符号也可以与指针一起使用。int main(){const int NUM_COINS = 5;double coins[NUM_COINS] = {0.05, 0.1, 0.25, 0.5, 1.0};double *doublePtr; // Pointer to a double// Assign the address of the coins array to doublePtrdoublePtr = coins;// Display the contents of the coins array// Use subscripts with the pointer!cout << setprecision (2);cout << "Here are the values in the coins array:\n";for (int count = 0; count < NUM_COINS; count++)cout << doublePtr [count] << " ";// Display the contents of the coins array again, but this time use pointer notation with the array name!cout << "\nAnd here they are again:\n";for (int count = 0; count < NUM_COINS; count++)cout << *(coins + count) << " ";cout << endl;return 0;}程序输出结果:Here are the values in the coins array: 0.05 0.1 0.25 0.5 1 And here they are again: 0.05 0.1 0.25 0.5 1当一个数组的地址分配给一个指针时,就不需要地址运算符了。由于数组的名称已经是一个地址,所以使用 & 运算符是不正确的。但是,可以使用地址运算符来获取数组中单个元素的地址。
c语言指针与数组,怎么联系起来?
1、指针的本质是一个与地址相关的复合类型,它的值是数据存放的位置(地址);数组的本质则是一系列的变量。
2、数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存。
3、当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。
指针与数组
数组名所代表的就是该数组最开始的一个元素的地址,在计算数组元素a[i]的值时,C语言实际上线将其转换为 (a+i)的形式,然后再进行求值。他们是等价的,可以将指针后面加下标,比如pa[i]和 (pa+i)是等价的,但是指针比单纯的数组名要快一些。 有一点很重要的,数组名和指针之间有一个不同之处,指针是一个变量,因此,pa+a和pa++都his合法的,但数组名不是变量(类似一个宏定义?用数组名替换地址?),所以进行对自身的增减运算是非法的。 有时如果将数组名传递给函数,函数可以根据情况判定是按照数组处理还是按照指针处理,随后根据相应的方式操作该函数,为了更直观的表示数组名和指针,可以同时使用两种表示方法。 也可以将数组的一部分传递给函数,不必须从起始位置运算、对于函数来说,它并不关心所引用的是否是一个大数组的其中一部分。 地址算数运算 *allocp = allocbuf起始是存储空间的起始位置。 之后的函数中allocbuf + ALLOCSIZE是存储空间的最后的地址,因为存储空间不一定是从0开始,所以起始地址加上总大小得到的就是这个存储空间最后的地址。减去allocp是将已分配的空间减去,得到的必然是小于或等于空间大小的数,这个数就是剩余的空间的大小。 这就比如从30000开始之后10000的部分是存储空间,已分配空间在35000那么30000加10000减去35000就是剩余的空间了。 之后的那个allocp自增让我懵了一下。自增之后为啥又减了,仔细看发现。allocp += n确实是自增了,本身的地址也改变了。但是allocp - n只是将数值传回了,并没有对自己赋值。 这个函数确实不完善,afree函数很简单就是确定参数的地址是否在存储空间内。是的话就将已分配的地址变成新的地址。 指针也可以初始化,对指针有意义的初始化只能是0或者是表示地址的表达式,表达式代表的地址必须是已经定义的具有适当类型的数据的地址。 static char *allocp = allocbuf; allocbuf需要在之前已经定义为字符数组才是有意义的。 C语言保证0永远不是有效的数据地址。因此,返回值0可用来表示发生了异常事件。 指针与整数之间不能相互转换,但0是唯一的例外,常熟0可以赋值给指针,指针也可以和常量0进行比较。程序中通常用符号常量NULL代替常量0。符号常量0定义在标准头文件中。 在某些情况下对指针可以进行比较运算。如果指针p和q是同一个数组的成员,那么他们之间就可以进行类似于==、!=、=的关系比较运算。任何指针与0进行相等或不等的比较运算都有意义。但是指向不同数组的元素的指针之间的算数或比较运算没有定义,(这里有一个特例。指针的算数运算中可使用数组最后一个元素的下一个元素的地址。) 指针可以和整数进行相加或相减运算。无论指针对象是何种类型都成立,相加的整数会根据指针指向的类型长度按比例缩放, 指针相减也是有意义的,同数组中的指针相减会得到指针之间字符的数量。 指针的算数运算具有一致性,所有的指针运算都会自动考虑它所指向的对象的长度。 有效的指针运算包括相同类型指针之间的赋值运算;指针同整数之间的加法或减法运算;指向相同数组中元素的两个指针间的减法或比较运算;将指针赋值为0或指针与0之间的比较运算。除此之外其他所有的指针运算都是非法的。(两个指针之一是void *类型的情况除外)
指针数组的创建和用法
创建:
(1)声明一个数组,声明时用常量表达式指定数组维数,然后可以用数组名访问数组元素。
(2)声明一个变长数组,声明时用变量表达式指定数组维数,然后用数组名来访问数组元素。
(3)声明一个指针,调用malloc(),然后使用该指针来访问数组元素。malloc接受一个参数:所需内存字节数。然后malloc()找到可用内存中一个大小合适的块。内存是匿名的;也就是说,malloc()分配了内存,但没有为它指定名字。然而,它却可以返回那块内存第一个字节的地址。因此,可以把那个地址赋值给一个指针变量,并使用该指针来访问那块内存。因为char代表一个字节,所以传统上曾将malloc()定义为指向char的指针类型。然而,ANSI
C标准使用了一个新类型:指向void的指针。这一类型被用作“通用指针”。函数malloc()可用来返回数组指针、结构指针等等,因此一般需要把返回值的类型指派为适当的类型。如果malloc()找不到所需的空间,它将返回空指针。我们使用malloc()来创建一个数组,可以在程序运行时使用malloc()请求一个存储块,另外还需要一个指针来存放该块在内存中的位置。例如,考虑以下代码:
double * ptd;
ptd = (double
*)malloc(30*sizeof(double));
使用第二种或第三种方法可以做一些用普通的数组声明做不到的事;创建一个动态数组(dynamic
array),即一个在程序运行时才分配内存并可在程序运行时选择大小的数组。例如,假定n是一个整数变量。在C99之前,不能这样做:
double item[n]; /*如果n是一个变量,C99之前不允许这样做*/
然而,即使在C99之前的编译器中,也可以这样做:
ptd=(double
*)malloc(n*sizeof(double));
变长数组VLA和malloc的用法有两点区别。一个区别在于VLA是自动存储的。自动存储的结果之一就是VLA所用内存空间在运行完定义部分之后会自动释放。因此不必使用free()。另一方面,使用由malloc()创建的数组不必局限在一个函数中。例如,函数可以创建一个数组并返回指针,供调用该函数的函数访问。接着,后者可以在它结束时调用free()。free()可以使用不同于malloc()指针的指针变量;必须一致的是指针中存储的位置。
用法:
//注意指针数组和数组指针分别是如何指向二维数组的
#include
main()
{
static int m[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
int (*p)[4];//数组指针 p是指针,指向一维数组,每个一维数组有4个int元素*p是个数组的地址,**p就是数组元素了
int i,j;
int *q[3];//指针数组 q是数组,数组元素是指针,3个int指针
p=m; //p是指针,可以直接指向二维数组
printf("--数组指针输出元素--\n");
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
printf("] ",*(*(p+i)+j));
}
printf("\n");
}
printf("\n");
for(i=0;i<3;i++,p++)//p可看成是行指针
{
printf("= ",**p);//每一行的第一个元素
printf("= ",*(*p+1));//每一行的第二个元素
printf("= ",*(*p+2));//每一行的第三个元素
printf("= ",*(*p+3));//每一行的第四个元素
printf("\n");
}
printf("\n");
printf("--指针数组输出元素--\n");
for(i=0;i<3;i++)
q[i]=m[i];//q是数组,元素q[i]是指针
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
printf("= ",q[i][j]);//q[i][j]可换成*(q[i]+j)
}
printf("\n");
}
printf("\n");
q[0]=m[0];
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
printf("= ",*(q[0]+j+4*i));
}
printf("\n");
}
printf("\n");
}