学习总结

1、数组初始化方式:

int a[]={1,2,3}

int a[SIZE]={1,2,3} //SIZE是宏定义,数组初始化个数不能大于SIZE,否则报错;当个数小

//SIZE,自动补0;只定义不初始化,默认值是当前存储单元中已有的数值。

int a[SIZE/不定长]={1,[3],2} //C99支持通过[int]=x来定义具体位置值,跳过的默认值为0。

2、通过const修饰的数组为只读数组,数组的每个元素当成常量来处理,如:

const int a[2]={1,2};

const int b[2];

a[1]=3; //编译不通过,无法修改,已有值2;

b[1]=3; //编译不通过,无法修改,已有默认存储单元数值。

3、数组赋值方式:

int a[]={1,2,3}; //允许

int a[2];a[1]=2; //允许

int a[2]={1,2};int b[2];b=a //不允许

int a[2];a[2]={1,2}; //不起作用

4、数据边界问题:数组的计数器是从0开始的,在标准C中,编译器是不会检查索引的合法性,因为C认为编译器在运行时逐个检查每个索引的合法代码会导致程序运行速度变慢,因此C会认为程序员的代码是正确的,但C太天真了,事情没有完美的,肯定存在人为出错因素,因此问题就产生了。不同编译器对于这种问题会出现不同的错误,所以要特别注意。

5、指定数组大小在C99之前是不允许通过变量定义,如

int n=2;

a[n]={1,2}; //C99前不允许,C99允许

6、二维数组初始化:

int a[2][3]={1,2,3,4,5,6}

int a[2][3]={{1,2,3},{4,5,6}}

按照二维表格排布,2相当于行数,3相当于列数。如a[2][3]={1,2,3,4,5,6}布局如下:

1 2 3

4 5 6

如a[3][2]={1,23,4,5,6}布局如下:

1 2

3 4

5 6

7、指针提供了一种用来使用地址的符号方法。由于计算机的硬件指令很大程度上依赖于地址,所以指针能够类似于计算机底层的表达,使工作更加高效。特别的,指针能够很有效的处理数组,数据实际上是一种变相使用指针的形式:

#include <stdio.h>
int main(){
int a[]={,};
printf("a=%p\n",a);
printf("a[0]=%p\n",&a[]);
return ;
}

打印结果:

a=0x7fff38352af0

a[0]=0x7fff38352af0

其实,数组名是该数组首元素的地址。

 #include <stdio.h>
int main(){
int a[]={,},*p;
p=a;
printf("&a=%p\n",&a);
printf("p=%p\n",p);
printf("a=%d\n",*a);
printf("p=%d\n",*p);
printf("---------------\n");
printf("a=%p\n",(a+));
printf("a=%d\n",*(a+));
p++;
printf("p=%p\n",p);
printf("p=%d\n",*p);
return ;
}

打印结果:

&a=0x7fffa1a350a0

p=0x7fffa1a350a0

a=1

p=1

---------------

a=0x7fffa1a350a4

a=2

p=0x7fffa1a350a4

p=2

从以上程序可以看出,数组指针加1,并非指针地址值加1,而是指向数组下一个元素的地址。

8、指针的基本操作:赋值、求值或取值、取指针地址、将一个整数加给指针、增加指针的值、从指针中减去一个整数、减小指针的值、求差值、比较。

 #include <stdio.h>

 int main(){
int urn[]={,,,,};
int *ptr1,*ptr2,*ptr3,*ptr4; printf("指针赋值\n");
ptr1 = urn;
printf("ptr1=%p\n",ptr1);
ptr2 = &urn[];
printf("ptr2=%p\n",ptr2); printf("指针求值或取值\n");
printf("(int)ptr1=%d\n",*ptr1);
printf("(int)ptr2=%d\n",*ptr2); printf("取指针地址\n");
printf("&ptr1=%p\n",&ptr1);
printf("&ptr2=%p\n",&ptr2); printf("将一个整数加给指针或增加指针的值\n");
ptr1++;
printf("ptr1=%p\n",ptr1);
printf("(int)ptr1=%d\n",*ptr1); printf("从指针中减去一个整数或减少指针的值\n");
ptr2--;
printf("ptr2=%p\n",ptr2);
printf("(int)ptr2=%d\n",*ptr2); printf("求差值");
ptr3 = &urn[];
ptr4 = &urn[];
printf("ptr4-ptr3=%d\n",ptr4-ptr3); printf("比较两个指针本身的值(非指针指向数据的值)");
printf("ptr4>ptt3=%d\n",ptr4>ptr3); return ;
}

运行结果:

指针赋值

ptr1=0x7fff886c8570

ptr2=0x7fff886c8578

指针求值或取值

(int)ptr1=100

(int)ptr2=300

取指针地址

&ptr1=0x7fff886c8568

&ptr2=0x7fff886c8560

将一个整数加给指针或增加指针的值

ptr1=0x7fff886c8574

(int)ptr1=200

从指针中减去一个整数或减少指针的值

ptr2=0x7fff886c8574

(int)ptr2=200

求差值

ptr4-ptr3=3

比较两个指针本身的值(非指针指向数据的值)

ptr4>ptt3=1

9、函数形参为数组时,一般是通过传递指针,如果是使用数组形参,那么函数中必须分配足够存放一份原数组拷贝的存储空间。为了避免函数不对原数组进行修改,可以通过const关键字对形参进行修饰,需要理解的是这样使用const并不要求原始数组固定不变的;这只是说明函数在处理数据时,应把数组当作是固定不变的。使用const可以对数组提供保护,就像值传递可以对基本类型提供保护一样。

int sum(int ar[],int n) //可以修改数组

int sum(const int ar[],int n) //不可修改数组

10、前面学习过可以使用const关键字来创建符号常量(const int PI=3.14159;),也可以是用#defined PI 3.15159来定义,但使用const还可以创建数组常量、指针常量以及指向常量的指针,使用const关键在于修饰的对象,修饰的对象不一样,效果也不同。

场景1:修饰数组

const int a[]={1,2,3,4,5};  //整个数组为常量数组,不可以修改。

a[0]=10;  //不允许

a[1]=11;  //不允许

场景2:修饰常量指针(指向常量的指针,常量为形容词,指针为名词,这样看,常量指针本质是指针,常量修饰它,表示这个指针乃是一个指向常量的指针)

int a[]={1,2,3,4,5};

const int *p=a;   //p指向数组的开始处

p[0]=10;  //不允许,因为指针指向常量,所以不能通过指针修改

a[0]=10;  //允许,但能通过数组本身修改,因为数组本身不是常量(特别注意)

场景3:修饰指针常量(指针是形容词,常量是名词。这回是以常量为中心的一个偏正结构短语。那么,指针常量的本质是一个常量,而用指针修饰它,那么说明这个常量的值应该是一个指针)

int a[]={1,2,3,4,5};

int * const p=a;

p[0]=10; //允许,数组非常量数组

p++;    //不允许,p为常量,不允许修改

p=&a[3]; //不允许,p为常量,不允许修改

11、二维数组a[4][2],其中a为数组首元素的地址,在本例中a首元素本身又是包含两个int的数组,如下所示:

a[0][0]=11=0x7fff908c0c60 a[0][1]=12=0x7fff908c0c64

a[1][0]=21=0x7fff908c0c68 a[1][1]=22=0x7fff908c0c6c

a[2][0]=31=0x7fff908c0c70 a[2][1]=32=0x7fff908c0c74

a[3][0]=41=0x7fff908c0c78 a[3][1]=42=0x7fff908c0c7c

a=0x7fff908c0c60         //二维数组首地址,a指向的对象是一个int数组(这里是两个int)

*a=0x7fff908c0c60        //*a就是一个int数组,跟a指向的是同一个int元素

*a+1=0x7fff0f1eebb4      //*a指向对象是一个int元素,加1就是向当前递增一个int

a+2=0x7fff908c0c70       //a指向的是一个int数组,加2就是向前地址两个int数组

*(a+2)=0x7fff908c0c70     //先是a向前地址两个int数组,再指向当前一维数组的首地址

*(a+2)+1=0x7fff908c0c74   //同*a

*(*(a+2)+1)=32           //取出上面地址的值

12、数组指针和指针数组的区别(参考百度网友解析):

int a[3][4]这个无需多说,就是一个二维数组。

int (*p)[4]就相当于int p[][4],它就是一个二维数组的指针,可以指向一个第二维度为4的二维数组。而a就是这样的数组,因而下面是合法的。

p=a;

int *p[3]是指针数组。说白了,就是定义了三个指针,分别为p[0],p[1],p[2]。可以将他们单独拿来使用。

int a1,a2,a3;

p[0]=&a1;

p[1]=&a2;

p[2]=&a3;

13、相对于数值类型的赋值,指针之间的赋值会更加的严格:

int n=5;

int *pi;

double x;

double pd;

x=n; //通过

pd=pi; //不通过

-------------------------例子分割线------------------------------------

int *pt;

int (*pa)[3];

int ar1[2][3];

int ar2[3][2];

int **p2;

pt = &ar1[0][0]; //pt是指向整数的指针,&a[0][0]也是指向整数的指针,所以合法

pt = ar1[0];    //ar1[0]同样是指向整数的指针,所以合法

pt = ar1;      // ar1是一个指向包含3位int数组的指针,和pt不一样,所以不合法

pa = ar1;      //pa是一个指向包含3位int数组的指针,和ar1一样,所以合法。

pa = ar2;      //ar2是一个指向包含2位int数组的指针,和pa不一样, 所以不合法

p2 = &pt;     //p2是指向整数指针的指针,pt是指向整数的指针,所以&pt与p2类型相同

*p2 = ar2[0];  //*p2是指向整数的指针,而ar2[0]同样是指向整数的指针,所以合法

P2 = ar2;     //ar2是指向一个包含2位int数组的指针,与P2不一样,所以不合法。

-------------------------例子分割线------------------------------------

int *p1;

const int *p2;

const int **pp2;

p1 = p2;    //非法把const指针赋值给非const指针

p2 = p1;    //合法把非const指针赋值给const指针

pp2= &p1;  //非法通过两层运算吧非const指针赋值给const指针,这样会引起赋值不安全详见P271例子。

14、编程题(题12)

 #include <stdio.h>

 int main(){
double d[][];
int i;
double sum1,sum2,sum3,maxDouble;
printf("enter 5 double for first doubleArr:\n");
for(i=;i<;i++){
scanf("%lf",&d[][i]);
} printf("enter 5 double for second doubleArr:\n");
for(i=;i<;i++){
scanf("%lf",&d[][i]);
} printf("enter 5 double for third doubleArr:\n");
for(i=;i<;i++){
scanf("%lf",&d[][i]);
} printf("thank you for your scanf.\n\n"); sum1=;
for(i=;i<;i++){
sum1+=d[][i];
if(i==)
maxDouble=d[][];
if(d[][i]>maxDouble)
maxDouble=d[][i];
}
printf("average value of first doubleArr is %f\n",sum1/); sum2=;
for(i=;i<;i++){
sum2+=d[][i];
if(d[][i]>maxDouble)
maxDouble=d[][i];
}
printf("average value of second doubleArr is %f\n",sum2/); sum3=;
for(i=;i<;i++){
sum3+=d[][i];
if(d[][i]>maxDouble)
maxDouble=d[][i];
}
printf("average value of third doubleArr is %f\n",sum3/); printf("average value of all double data is %f\n",(sum1+sum2+sum3)/);
printf("the max double is %f\n",maxDouble); return ;
}

运行结果:

enter 5 double for first doubleArr:

11

12

13

14

15

enter 5 double for second doubleArr:

21

22

23

24

25

enter 5 double for third doubleArr:

31

32

33

34

35

thank you for your scanf.

average value of first doubleArr is 13.000000

average value of second doubleArr is 23.000000

average value of third doubleArr is 33.000000

average value of all double data is 115.000000

the max double is 35.000000

【C语言学习】《C Primer Plus》第10章 数组和指针的更多相关文章

  1. C Primer Plus 第10章 数组和指针 编程练习

    这章感觉好难啊,放个别人的总结. // 多维数组和指针 #include <stdio.h> int main(void) { int zippo[4][2] = {{2, 4}, {6, ...

  2. 12天学好C语言——记录我的C语言学习之路(Day 10)

    12天学好C语言--记录我的C语言学习之路 Day 10: 接着昨天的指针部分学习,有这么一个题目: //还是四个学生,四门成绩,只要有学生一门功课没及格就输出这个学生的所有成绩 /*//progra ...

  3. 《Go语言实战》笔记之第四章 ----数组、切片、映射

    原文地址: http://www.niu12.com/article/11 ####数组 数组是一个长度固定的数据类型,用于存储一段具有相同的类型的元素的连续块. 数组存储的类型可以是内置类型,如整型 ...

  4. C++ Primer高速入门之六:数组和指针

    更新:勘误,delete [] 猪 我们知道,C语言以及早期的面向结构的语言差点儿都支持数组定义.比方整形数组int 女神[2].表示有俩数: 女神[0], 女神[1].她们都是整数. C++ 语言为 ...

  5. Java程序设计基础笔记 • 【第10章 数组】

    全部章节   >>>> 本章目录 10.1 数组概述 10.1.1 数组优势 10.1.2 Java中的数组 10.1.3 数组的分类 10.2 一维数组 10.2.1 数组的 ...

  6. C Primer Plus_第10章_数组和指针_编程练习

    1. /*rain.c 针对若干年的降水量数据,计算年降水总量.年降水平均量,以及月降水平均量*/ #include <stdio.h> #define MONTHS 12 #define ...

  7. 《C++ primer》--第10章

    习题10.21 解释map和set容器的差别,以及他们各自适用的情况. 解答: map容器和set容器的差别在于: map容器是键-值对的集合,而set容器只是键的集合: map类型适用于需要了解键与 ...

  8. C++ Primer 5th 第10章 泛型算法

    练习10.1:头文件algorithm中定义了一个名为count的函数,它类似find,接受一对迭代器和一个值作为参数.count返回给定值在序列中出现的次数.编写程序,读取int序列存入vector ...

  9. [C++ Primer Plus] 第10章、对象和类(一)程序清单——辨析三个const

    程序清单10.1+10.2+10.3 头文件stock.h #ifndef STOCK00_H_ //先测试x是否被宏定义过 #define STOCK00_H_ //如果没有宏定义,就宏定义x并编译 ...

随机推荐

  1. Http协议的常见参数

    Requests部分 Header 解释 示例 Accept 指定客户端能够接收的内容类型 Accept: text/plain, text/html Accept-Charset 浏览器可以接受的字 ...

  2. 兼容ie8 rgba()用法

    今天遇到了一个问题,要在一个页面中设置一个半透明的白色div.这个貌似不是难题,只需要给这个div设置如下的属性即可: background: rgba(255,255,255,.1); 但是要兼容到 ...

  3. js中typeof与instanceof用法区别

    今天写JS代码,遇到动态生成多个名称相同的input复选按钮 需要判断其是否是数组,用到了if (typeof(document.MapCheckMgr.checkid)!="undefin ...

  4. css鼠标手型cursor中hand与pointer

    css鼠标手型cursor中hand与pointer Example:CSS鼠标手型效果 <a href="#" style="cursor:hand"& ...

  5. JavaScript中对象的含义与this的指向

    JavaScript中的对象:无序属性的集合 -其属性可以包含基本值.对象或函数.对象就是一组没有顺序的值.我们可以吧JavaScript中的对象想象成键值对,其中值可以是数据和函数.对象的行为和特征 ...

  6. java 8种基本数据类型的默认值及所占字节数

    通过一段代码来测试一下 8种基本数据类型的默认值 package dierge; public class Ceshi { int a; double b; boolean c; char d; fl ...

  7. Java 第7章 数组

    第七章 (数组) 为什么需要数组 java 考试结束后,老师给张浩分配了一项任务,让他计算全班(30人)的平均分 int stu1=95; int stu2=95; int stu3=95; int ...

  8. 使用jailkit chroot更改ssh用户根目录

    安装jailkit cd /tmp    wget http://olivier.sessink.nl/jailkit/jailkit-2.16.tar.gz    tar xzf jailkit-2 ...

  9. Ubuntu-14.04.3下SDL2测试

    最近突然蛋痛想入门Linux,想写个跨平台的游戏,各种坑,备忘,稍微记点笔记. 主要参考这个文章 buntu14.04下C++开发SDL2应用 下载与安装 到http://www.libsdl.org ...

  10. lvs-keepalived故障记录

    上图中1与2.3不同,可能会导致端口不同,尽量配置1.2.3相同