Cprimer day10 数组和指针

数组和指针

数组

int main(){
	float candy[365];   //内含365个float类型元素的数组
    char [12];  //内含12个char类型元素的数组
    int state[50];   //内含50个int类型的元素的数组
}

初始化数组

int power[8] = {1,2,4,6,8,32,64};
int days[] = {30,21,32,36,54};
int n=5;
int arr[n];
指定初始化器(C99)
#include <stdio.h>
#define MONTH 12
int main(){
    int days[MONTH] = {31,28,[4]=31,30,30,[1]=29,30};
    int i;
    for (i = 0; i<MONTH; i++)
    printf("%2d %d\n",i+1,days[i]);
    return 0;
}
 1 31
 2 29
 3 30
 4 0
 5 31
 6 30
 7 30
 8 0
 9 0
10 0
11 0
12 0
给数组元素赋值
int counter, evens[SIZE]; 
for (counter = 0; counter < SIZE; counter++) 
evens[counter] = 2 * counter;

无效

int oxen[SIZE] = {5,3,2,8};
int yaks[SIZA];
yaks = oxen;  //不允许这样赋值
yaks[SIZE] = oxen[SIZE]; //超出数组维度  第六个值不存在 也就不能赋值  
yaks[SIZE] = {5,3,2,8};  //不起作用 
数组边界
#include <stdio.h>
#define SIZE 4
int main(){
    int value1 = 44;
    int arr[SIZE];
    int value2 = 88;
    int i;
    printf("value1 = %d,value2 = %d\n",value1,value2);
    for (i = -1;i <= SIZE;i++)
    arr[i] = 2*i +1;
    for (i = -1; i < 7; i++)
    printf("%2d %d\n",i,arr[i]);
    printf("value1 = %d,value2 = %d\n",value1,value2);
    printf("address of arr[-1]: %p\n",&arr[-1]);
    printf("address of arr[4]: %p\n",&arr[4]);
    printf("address of value1: %p\n",&value1);
    printf("address of value2: %p\n",&value2);
    return 0;
}
value1 = 44,value2 = 88
-1 -1
 0 1
 1 3
 2 5
 3 7
 4 9
 5 0
 6 44
value1 = 44,value2 = -1  //value2储存了[-1] [6]储存了value1
address of arr[-1]: 000000000061FDFC
address of arr[4]: 000000000061FE10
address of value1: 000000000061FE18
address of value2: 000000000061FDFC

这都是因为C不检查边界,故要小心。

多维数组

float rain[5][12];

在这里插入图片描述

初始化二维数组

初始化数组**

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DyX6hPEr-1589093856557)(E:\Program_learning\C_Recrods\day10\数组和指针.assets\image-20200505091128501.png)]

其他多维数组
// 三位数组定义
int box[10][20][30];

指针和数组

在这里插入图片描述

#include <stdio.h>
#define MONTH 12
int main(){
    long int days[MONTH] = {31,28,31,30,31,30,31,31,30,31,30,31};
    long index;
    for (index = 0;index < MONTH;index++)
    printf("MONTH %2d has %d days.\n",index+1,*(days+index));   //*(days+index)  equal days[index]
    return 0;
}

函数、数组和指针

int sum(int *ar);  // int sum(int ar[]);
int sum(int *ar){
    int i; 
    int total = 0;
    for (i = 0; i < 10; i++)
        total += ar[i];
    return total;
}

函数原型声明等价

int sum(int *ar,int n);
int sum(int *,int);
int sum (int ar[],int n);
int sun(int [],int);

函数定义等价

int sum(int *ar,int n){
...
}

int sum(int ar[],int n){
...
}
#include <stdio.h>
#define SIZE 10
int sum( int *ar, int);
int main(){
    int marbles[SIZE] = {20,10,5,39,4,16,19,26,31,20};
    long answer;
    answer = sum(marbles,SIZE);
    printf("The total number of mables is %ld.\n",answer);
    printf("The size of marbles is %zd bytes.\n",sizeof marbles);
    return 0; 
}
int sum(int *ar,int n){  //最好用*ar 而不是 ar[]
    int i;
    int total =0;
    for (i = 0; i < n; i++)
    total += ar[i];
    printf("The size of ar is %zd bytes.\n",sizeof ar);
    return total;
}
使用指针形参
#include <stdio.h>
#define SIZE 10
int sump(int *start,int *end);
int main(){
    int marbles[SIZE] = {20,10,5,39,4,16,19,26,31,20};
    long answer;
    printf("%d,%d",marbles,marbles+SIZE);
    answer = sump(marbles,marbles + SIZE);  //传送地址
    printf("The total number of mables is %ld.\n",answer);
    return 0;
}
int sump(int *start,int *end){
    int total = 0;
    while (start < end)
    {
        total += *start;
        start++;
    }
    return total;
}
#include <stdio.h>
int data[2] = {100,200};
int moredate[2] = {300,400};
int main(){
    int *p1,*p2,*p3;
    p1 = p2 = data;
    p3 = moredate;
    printf(" *p1 =%d, p2 = %d,   *p3 = %d\n",*p1,*p2,*p3);
    printf(" *p1++ = %d, *++p2 = %d, (*p3)++ = %d\n",*p1++,*++p2,(*p3)++);
    printf(" *p1 = %d,*p2 = %d, *p3 = %d.\n",*p1,*p2,*p3);
    return 0;
}

指针操作

#include <stdio.h>
int main(){
    int urn[5] = {1,2,3,4,5};
    int *ptr1,*ptr2,*ptr3;
    ptr1 = urn;
    ptr2 = &urn[2];
    printf("pointer value, dereferenced pointer, pointer address:\n");
    printf("ptr1 = %p, *ptr1 =%d, &ptr1 = %p\n", ptr1, *ptr1, &ptr1);
    ptr3 = ptr1 + 4;
    printf("\nadding an int to a pointer:\n");
    printf("ptr1 + 4 = %p, *(ptr1 + 4) = %d\n", ptr1 + 4, *(ptr1 + 4));
    ptr1++;
    printf("\nvalues after ptr1++:\n");
    printf("ptr1 = %p, *ptr1 =%d, &ptr1 = %p\n", ptr1, *ptr1, &ptr1);
    ptr2--;
    printf("\nvalues after --ptr2:\n");
    printf("ptr2 = %p, *ptr2 = %d, &ptr2 = %p\n", ptr2, *ptr2, &ptr2);
    --ptr1;
    ++ptr2;
    printf("\nPointers reset to original values:\n");
    printf("ptr1 = %p, ptr2 = %p\n", ptr1, ptr2);
    printf("\nsubtracting one pointer from another:\n");
    printf("ptr2 = %d, ptr1 = %d, ptr2 - ptr1 = %d\n",ptr2, ptr1, ptr2 - ptr1);
    printf("ptr2 = %p, ptr1 = %p, ptr2 - ptr1 = %td\n",ptr2, ptr1, ptr2 - ptr1);
    printf("\nsubtracting an int from a pointer:\n");
    printf("ptr3 = %p, ptr3 - 2 = %p\n", ptr3, ptr3 - 2);
    return 0;
}
ptr1 = 000000000061FE00, *ptr1 =1, &ptr1 = 000000000061FDF8

adding an int to a pointer:
ptr1 + 4 = 000000000061FE10, *(ptr1 + 4) = 5

values after ptr1++:
ptr1 = 000000000061FE04, *ptr1 =2, &ptr1 = 000000000061FDF8

values after --ptr2:
ptr2 = 000000000061FE04, *ptr2 = 2, &ptr2 = 000000000061FDF0

Pointers reset to original values:
ptr1 = 000000000061FE00, ptr2 = 000000000061FE08

subtracting one pointer from another:
ptr2 = 6422024, ptr1 = 6422016, ptr2 - ptr1 = 2
ptr2 = 6422024, ptr1 = 6422016, ptr2 - ptr1 = 2

subtracting an int from a pointer:
ptr3 = 000000000061FE10, ptr3 - 2 = 000000000061FE08

在这里插入图片描述

错误

int *pt;
*pt=5;

保护数组中的数据

对形参 使用const
#include <stdio.h>
#define SIZE 5
void show_array(const double ar[],int n); //不需要改变数组值
void mult_array(double ar[], int n, double mult);  //需要改变数组值
int main(){
    double dip[SIZE]= { 20.0, 17.66, 8.2, 15.3, 22.22 };
    printf("The original dip array:\n");
    show_array(dip, SIZE);
    mult_array(dip, SIZE, 2.5);
    printf("The dip array after calling mult_array():\n");
    show_array(dip, SIZE);
    return 0;
}
void show_array(const double ar[],int n){
    int i;
    for (i = 0; i < n;i++)
    printf("%8.3f ", ar[i]); 
    putchar('\n');
}
void mult_array(double ar[],int n, double mult){
    int i;
    for (i = 0;i<n;i++)
    ar[i] *= mult; 
}
const的其他内容
const int arr[3]={1,2,3};  //arr数组值不能改变
double arr2[4] ={1,2,3,4};
const double *pd = arr2;
*pd = 29.89;    //不允许
pd[2] = 222.22;     // 不允许
arr2[0] = 99.99; // 允许,因为arr2未被const限定
pd++;  //允许改变地址

把const数据或非const数据的地址初始化为指向const的指针或为其赋值是合法的。

double rates[5] = {88.99, 100.12, 59.45, 183.11, 340.5}; 
const double locked[4] = {0.08, 0.075, 0.0725, 0.07};
const double * pc = rates; // 有效
pc = locked;//有效
pc = &rates[3]; //有效

只能把非const数据的地址赋给普通指针。

double * pnc = rates;// 有效 
pnc = locked;      // 有效
pnc = &rates[3]; // 无效 

不应该把const数组名作为实参传递给改变数组值的函数

可以声明并初始化一个不能指向别处的指针,关键是const的位置

double * const pc = rates; // pc指向数组的开始
pc = &rates[2];    // 不允许,因为该指针不能指向别处
*pc = 92.99   //可以更改rates[0]的值

在创建指针时还可以使用const两次,该指针既不能更改它所指向的地址,也不能修改指向地址上的值

const double * const pc = rates;
pc = &rates[2];//不允许 
*pc = 92.99; //不允许

指针和多维数组

#include <stdio.h>
int main(){
    int zippo[4][3] = {{2,4,1}, { 6,8,1 }, { 1,3 ,5},{ 5,7,6}}; //[4][1]
    printf("zippo = %p, zippo + 1 = %p\n",zippo, zippo+ 1);
    printf("zippo[0] = %p, zippo[0] + 1 = %p\n",zippo[0],zippo[0] + 1);
    printf(" *zippo = %p, *zippo + 1 = %p\n",*zippo, *zippo + 1);
    printf("zippo[0][0] = %d\n", zippo[0][0]);
    printf(" *zippo[0] = %d\n", *zippo[0]);
    printf(" **zippo = %d\n", **zippo);
    printf("zippo[2][1] = %d\n", zippo[2][1]);
    printf("*(*(zippo+2) + 1) = %d\n", *(*(zippo + 2) + 1));
    return 0;
}
zippo = 000000000061FDF0, zippo + 1 = 000000000061FDFC  //指向第一维数组地址
zippo[0] = 000000000061FDF0, zippo[0] + 1 = 000000000061FDF4
 *zippo = 000000000061FDF0, *zippo + 1 = 000000000061FDF4
zippo[0][0] = 2
 *zippo[0] = 2
 **zippo = 2
zippo[2][1] = 3
*(*(zippo+2) + 1) = 3

在这里插入图片描述
在这里插入图片描述

指针的兼容性
//  不允许不同类型的指针赋值
int n = 5;
doubles x;
int *p1 = &n;
double *pd = &x
pd = p1; //编译错误
int * pt;
int (*pa)[3];//定义指向3个int类型元素的指针
int **p2; // 一个指向指针的指针
int ar1[2][3];
int ar2[3][2];
pt = &ar1[0][0];   //都是指向int的指针
pt = ar1[0];   //都是指向int的指针
pt = ar1;    //无效  arr1指向3个int类型
pa = ar1;  //都指向指向3个int类型元素的指针
pa = ar2;   //无效
p2 = &pt;   //
*p2 = ar2[0]; //ar2[0]指向ar2[0][0]的地址  ar2是指针
p2 = ar2; //ar2指向2个int
int x =20;
const int y = 23;
int * p1 = &x;
const int * p2 = &y;
const int ** pp2;
p1 = p2;     // 不安全 -- 把const指针赋给非const指针 p2没有地址能力
p2 = p1;   // 有效 -- 把非const指针赋给const指针 此时的p2可以改变地址
pp2 = &p1;    //不安全  嵌套指针类型赋值   不加const可以赋值
函数和多维数组
int sum2(int ar[][4], int rows);  // 标准形式
int sum4d(int ar[][12][20][30], int rows);  //第1对方括号只用于表明这是一个指针

变长数组

int sum2d(int rows, int cols, int ar[rows][cols]); // ar是一个变长数组
int sum2d(int ar[rows][cols], int rows, int cols); // 无效的顺序

复合字面量

(int[]){1234}   //[]可写可不写
//一般用法
int * pt1;
pt1 = (int [2]) {10, 20};
//一般用法
int (*pt2)[4];
pt2 = (int [2][4]) { {1,2,3,-9}, {4,5,6,-8} };
//作为实参传递
int sum(const int ar[], int n);
...
int total3; 
total3 = sum((int []){4,4,4,5,5,5}, 6);

复习题

数组名 不可以自加自减

psa是一个内含20个元素的数组,每个元素都是指向int的指针。

int *psa[20];

pstr是一个指向数组的指针,该数组内含20个char类型的值。

char (*pstr)[20];

假设编译器支持C99/C11标准,声明一个内含100个int类型值的数组,并初始化最后一个元素为-1,其他元素不考虑。

int arr[100]= {[99]=-1};

假设编译器支持C99/C11标准,声明一个内含100个int类型值的数组,并初始化下标为5、10、11、12、13的元素为101,其他元素不考虑。

int pots[100] = { [5] = 101, [10] = 101,101, 101, 101};


int sum(const int ar[], int n);

int total3;
total3 = sum((int []){4,4,4,5,5,5}, 6);


### 复习题

数组名 不可以自加自减

psa是一个内含20个元素的数组,每个元素都是指向int的指针。

```c
int *psa[20];

pstr是一个指向数组的指针,该数组内含20个char类型的值。

char (*pstr)[20];

假设编译器支持C99/C11标准,声明一个内含100个int类型值的数组,并初始化最后一个元素为-1,其他元素不考虑。

int arr[100]= {[99]=-1};

假设编译器支持C99/C11标准,声明一个内含100个int类型值的数组,并初始化下标为5、10、11、12、13的元素为101,其他元素不考虑。

int pots[100] = { [5] = 101, [10] = 101,101, 101, 101};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值