2025年数组和指针(一)

数组和指针(一)数组 初始化 int some data 4 14 10 其中 some data 2 和 some data 3 的值为 0 但初始化列表中的值少于 数组元素个数时 编译器会把剩余的元素都初始化为 0 如果初始化列表中的值多于 数组元素个数时 编译器会无情地将其视为错误

大家好,我是讯享网,很高兴认识大家。

数组

初始化

 int some_data[4]={ 
   14,10}; 其中some_data[2]和some_data[3]的值为0

讯享网

但初始化列表中的值少于数组元素个数时,编译器会把剩余的元素都初始化为0。
如果初始化列表中的值多于数组元素个数时,编译器会无情地将其视为错误

讯享网 const int days[]={ 
   31,28,31}; 其实,可以省略方括号中的数字,让编译器自动匹配数组大小和初始化列表中的项数。 

初始化指定器

int arr[6]={ 
   [5]=212}; // 把arr[5]初始化为212 

对于一般的初始化,在初始化一个元素后,未初始化的元素都会被设置为0。

讯享网#define MONTHS 12; int days[MONTHS]={ 
   31,28,[4]=31,30,31,[1]=29}; int i; for(i=0;i<MONTHS;i++) printf("%2d %d\n" ,i+1,day[i]; 输出为: 1 31 2 29 3 0 4 0 5 31 6 30 7 31 8 0 9 0 10 0 11 0 12 0 

第1条:c不允许把数组作为一个单元赋给另一个数组;
第2条:除初始化以外也不允许使用花括号列表的形式赋值
下面演示一些错误的赋值形式:

#define SIZE 5 int main(void) { 
    int oxen[SIZE]={ 
   5,3,2,8}; //这样初始化没问题 int yaks[SIZE]; yaks=oxen; //不允许,违反了第1条 yaks[SIZE]=oxen[SIZE]; //数组下标越界,解释在下面 yaks[SIZE]={ 
   5,3,2,8}; //不起作用,违反第2条 

二维数组

二维数组在计算机内部是按顺序存储的

在这里插入图片描述
讯享网
rain是一个含有5个元素,每个元素又含有12个float类型元素的数组。

初始化二维数组(可以使用两个嵌套的for循环)

在这里插入图片描述

  1. 用逗号分隔5个数值列表,每个数值列表都用花括号括起来。
    第1个列表的数据用于初始化第一行,第2个列表用于初始化第2行,以此类推。
  2. 此外,前面讨论的数据个数和数组大小不匹配问题同样适用于这里的每一行。
    也就是说,如果第1列表中只有10个数,则只会初始化第1行前10个元素,而最后两个元素被默认初始化为0。 如果列表中的数值个数超出了数组每行的元素个数,则会出错,但不会影响其他行。
  3. 初始化也可以省略内部的花括号,但会按照先后顺序逐行初始化。

下面演示了初始化二维数组的两种方法:
在这里插入图片描述

其他多维数组

讯享网int box[10][20][30]; 

可以把一维数组想象成一行数据;二维数组想象成数据表;把三维数组想象成一叠数据表。(可以把box想象成由10个二维数组(每个二维数组都是20行30列)堆叠起来的)。

指针和数组

  1. 数组变量是特殊的指针
    例子:数组名是数组首元素的地址。flizny是一个数组
flizny==&flizny[0]; //数组名是该数组首元素的地址 
讯享网int a[10]; int*p=a; //无需用&取地址` 
int k=*p; *p=k+1; 
  1. 指针是const
    表示一旦得到了某个变量的地址,不能再指向其他变量
讯享网int*const q=&i; //q是const *q=26//OK q++; //ERROR 

所指是const
表示不能通过这个指针去修改那个变量(并不能使得那个变量成为const)

const int*p=&; *p=26; //ERROR!(*p)是const i=26; //OK p=&j; //OK 

指针运算

  1. 指针加上一个整数或递增指针,指针的值以所指向对象的大小为单位(字节为度量)改变。也就是说,如果pd指向一个数组的8字节double类型值,那么pd加1意味着其值加8,以便它指向该数组的下一个元素。
讯享网short *pti; double*ptf; printf("%d %d\n",pti,ptf); printf("%d %d",pti+1,ptf+1); 
输出: 0x7fff5fbff8dc 0x7fff5fbff8a0 0x7fffafbff8de 0x7fff5fbff8a8 

0x7fff5fbff8dc+1是否是 0x7fff5fbff8de?
0x7fff5bff8a0+1是否是0x7fff5bff8a8?
在系统里,地址按字节编址,short类型占用2字节,double类型占用8字节。
在指针加1指的是增加一个存储单元。对数组而言,加1后的地址是下一个元素的地址,而不是下一个字节的地址。
在这里插入图片描述

讯享网dates+2==&date[2] //相同的地址 *(dates+2==dates[2] //相同的值 再次强调一下,数组名是该数组首元素的地址 

ar[n]的意思是*(ar+n)。可以认为 *(ar+n)的意思是“到内存的ar位置,然后移动n个单元,检索存储在那里的值。”

*(dates+2//dates第3个元素的值 *date+2 //dates第1个元素的值加2 

在这里插入图片描述
2. *p++
意思是:取出p所指的那个数据来,完事之后顺便把p移到下一个位置去
常用于数组类的连续空间操作。

3. 指针比较
<,<=,==,>,>=,!=都可以对指针做
比较它们在内存中的地址
数组中的单元的地址肯定是线性递增的
4. 0地址
0地址通常是个不能随便碰的地址。
可以用0地址来表示特殊的事情:返回的指针是无效的;指针没有被真正初始化(先初始化为0)。
NULL是一个预定定义的符号,表示0地址。

函数、数组和指针

  1. int*ar形式和int ar[ ]形式都表示ar是一个指向int类型的指针。但是,int ar[ ]只能用于声明形式参数。第2种形式提醒读者指针ar指向的不仅仅一个int类型值,还是一个int类型数组的元素。
讯享网int sum(int*ar); //对应的函数原型 sum(marbles); /*可能的函数调用;sum()从实参获得了该数组首元素的地址 知道要在这个位置找出一个整数*/ int sum(int*ar) //函数定义 { 
    int i; int total=0; for(i=0;i<10;i++) //假设数组有10个元素 { 
    total+=ar[i]; //ar[i]和*(ar+1)相同 return total; } } 

第二种:把数组大小作为第2个形参:

int sum(int*ar); //对应的函数原型 sum(marbles); /*可能的函数调用;sum()从实参获得了该数组首元素的地址 知道要在这个位置找出一个整数*/ int sum(int*ar,int n) //函数定义 { 
    int i; int total=0; for(i=0;i<n;i++) //假设数组有10个元素 { 
    total+=ar[i]; //ar[i]和*(ar+1)相同 return total; } } 
讯享网int sum(int *ar); int marbles[10]={ 
   0}; answer=sum(marble); printf("%zd bytes",size marbles); int sum(int *ar) { 
    printf("%zd bytes",sizeof ar); } 输出: 8 bytes 40 bytes 
使用指针形参

在这里插入图片描述
. c保证在给数组分配空间时,指向数组后面第一个位置的指针仍是有效的指针。
使用这种“越界”指针的函数调用更为简洁。

为什么数组传进函数后的sizeof不对了?

  1. 函数参数表中的数组实际上是指针。
    sizeof(a)==sizeof(int*)。
    但是可以用数组的运算符[ ]进行运算。
    示例:
//这里的knownPrimes[]实际上是指针。 int isPrimes(int x, int knownPrimes[], int numberofKnownPrimes) { 
    int ret = 1; int i; for (i = 0; i < numberofKnownPrimes; i++) { 
    if (x % knownPrimes[1] == 0) { 
    ret = 0; break; } } return 0; } 

数组参数

以下四种函数原型是等价的:

讯享网1. int sum(int*ar,int n); 2. int sum(int*,int); 3. int sum(int ar[],int n); 4. int sum(int[],int); 

指针常见的错误

定义了指针变量,还没有指向任何变量,就开始使用指针。

指针的类型

数组的大小

sizeof(a)给出整个数组所占据的内容的大小,单位是字节。
sizeof(a[0])给出数组中的单个元素的大小,于是相除就得到了数组的单元个数。
优点:这样的代码,一旦修改数组中初识的数据,不需要修改遍历的代码。

小讯
上一篇 2025-03-03 14:14
下一篇 2025-01-27 08:39

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/42670.html