C Primer Plus 读书笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_20440225/article/details/79841062

编译器是把源代码转换成可执行代码程序。

连接器是用来链接库函数。

#include是预处理指令。C编辑器在编译前会对源代码做一些准备工作,即预处理。

#符号表明,C预处理器在编译器接手之前处理这条指令。

所有的C编译器软件包都提供stdio.h文件,该文件包含了供编译器使用的输入、输出函数。

stdio.h的含义是标准输入/输出头文件。

通常,C语言程序顶部的信息集合被称为头文件

头文件可以定义一些常量,或者指明函数名以及如何使用他们。

int main(void)----mian()函数总是第一个被调用的函数,C程序一定从main()函数开始执行。int是main()函数的返回类型。这表明main()函数返回的值是整数。通常,函数名后面的圆括号中包含一些传入函数的信息。void表示不传递任何信息。

C语言中的6种语句:标号语句,复合语句、表达式语句、选择语句、迭代语句、跳转语句。

声明 int num;

声明完成了两件事:一、在函数中有一个名为num的变量;二、int表明num是一个整数。

num是一个标识符,也就是一个变量、函数或者其它实体的名称。

C语言中,所有变量都必须先声明才能使用。这意味着必须列出程序中所用的所有变量名及其类型。关键字不能用作于标识符。

命名 

一、命名要有意义;二、可以使用大、小写字母、数字、和下划线来命名;三、首个字符必须是字符或者下划线;四、区分大小写。

赋值  例:num = 1;该赋值表达式语句从右侧把值赋给左侧,并且该语句以分号结尾。

printf()函数。圆括号表明printf是一个函数名。圆括号中的内容是从main()函数传递给printf()函数的信息。例如:把printf("Iam a simple");里面的I am asimple传递给printf()函数。该信息被称为参数,或者更确切的说,是函数的实际参数,简称实参。实参是传递给函数的特定值;形参是函数中用于储存值的变量。

\n组合代表一个换行符。换行符是一个转义序列。转义序列用于代表难以表示或者无法输入的字符。例如:\t代表Tab键,\b代表Backspace键(退格键)。每个转义序列都以反斜杠字符(\)开始。

%d相当于一个占位符,其作用是知名输出num值的位置。d表明把变量作为十进制整数打印。

return语句,return后面是待返回的值。

语法错误:语法错误指的是把有效的C符号放在错误的地方。

语义错误:语义错误指的是意思上的错误。

程序状态:程序状态是在程序的执行过程中,某给定点上所有变量值的集合。它是计算机当前状态的一个快照。

有些数据类型在程序使用之前已经预先设定好了,在整个程序的运行过程中没有变化,这些称为常量(constant)。

其他数据类型在程序运行期间可能会改变或被赋值,这些称为变量(variable)。

int类型是有符号整形,即int类型的值必须是整数,可以是正整数、负整数或零。

ISO 规定C语言下的int的取值范围为-32768-32767.

C语言提供三个附属关键字修饰基本整数类型:shortlongunsigned

short int类型(简写short)占用的存储空间可能比int类型少,常用于较小数值的场合以节省空间。与int类似,short是有符号类型。

long intlong占用的存储空间可能比int多,适用于较大数值的场合。与int类似,long是有符号类型。

long long intlong longC99标准加入)占用的存储空间可能比long多,适用于更大数值的场合。该类型最少占位64位。有符号类型。

unsigned intunsigne只用于非负数值的场合。取值范围是0~65535。

#include<stdio.h>

intmain(void)

{

       int ten = 10;

       int two = 2;

       printf("%d minus %d is %d\n",ten, 2, ten - two);

       printf("Doing it wrong: ");

       printf("%d minus%dis%d\n",ten);

       getchar();

       return 0;

}

/*

       第一行:

       第一个:%d对应int类型变量ten;

       第二个:%d对应int类型常量2;

       第三个:%d对应int类型表达式ten-two的值。

       第二行中:

       第一个:%d对应ten的值;

       由于没有给后两个%d提供任何值,所以打印出来的值是内存中的任意值。

0x或者OX前缀表示十六进制值,O前缀表示八进制值。特别:使用不同的进制是为了方便,不会影响数被存储的方式。

       以十进制显示数字,要使用%d;

       以八进制显示数字,要使用%o;

       以十六进制显示数字,要使用%x;

       如果要显示各进制数的前缀00xOX必须分别使用%#o%#x%#X

*/

#include<stdio.h>

intmain(void)

{

       float weight;

       float value;

       printf("Are you worth your weight inplatinum?\n");

       printf("Let's check itout.\n");

       printf("Please enter your weight inpounds: ");

       scanf("%f", &weight);

       value = 1700.0 * weight * 14.5833;

       printf("Your weight in platinum isworth $%.2f.\n", value);

       printf("You are easily worth that!If platinum prices drop,\n");

       printf("eat more to maintain yourvalue.\n");

       return 0;

}

/*

       加入新的类型----float,浮点值类型。

       pinrtf()中使用%f来处理浮点值。%.2f中的.2用于精确控制输出,指定输出的浮点数只显示小数点后面两位。

      scanf()函数用于读取键盘输入。%f说明scanf()要读取用户从键盘输入的浮点数,&weight告诉scanf()把输入的值赋给名为weight的变量。scanf()函数使用&符号表明找到weight变量的地点。

*/

#include<stdio.h>

intmain(void)

{

       int i = 214783647;

       unsigned int j = 4294967295;

       printf("%d %d %d\n", i, i + 1,i + 2);

       printf("%u %u %u\n", j, j + 1,j + 2);

       unsigned int un = 3000000000;

       short end = 200;

       long big = 65537;

       long long verybig = 12345678908642;

       printf("un = %u and not %d\n",un, un);

       printf("end = %hd and %d\n",end, end);

       printf("big = %ld and %hd\n",big, big);

       printf("verybig = %lld and not%ld\n", verybig, verybig);

       getchar();

       return 0;

}

/*

       打印unsign类型的值,使用%u转换说明;

       打印long类型的值,使用%ld转换说明;

       以十六进制格式打印long类型整形,使用%lx表示;

       以八进制格式打印long类型整型,使用%lo来表示。

       对于short类型,可以使用h前缀。

       %hd表示以十进制显示short类型的整数,

       %ho表示以八进制显示short类型的整数,

       h和l前缀都可以和u一起使用,用于表示无符号类型。

       %lu表示打印unsignedlong类型的值。

       %lld和%llu分别表示有符号和无符号类型。

       char类型用于存储字符(例如:字母或者标点符号),但从技术层面来看,char是整数类型。

       char类型实际上储存的是整数而不是字符。

       C语言把1字节定义为char类型占用的位(bit)数。

       C语言中,用单引号括起来的单个字符被称为字符常量。单引号必不可少。

       双引号代表的是字符串。

       %c指明待打印的字符。

*/

#include<stdio.h>

intmain(void)

{

       int i = 214783647;

       unsigned int j = 4294967295;

       printf("%d %d %d\n", i, i + 1,i + 2);

       printf("%u %u %u\n", j, j + 1,j + 2);

       unsigned int un = 3000000000;

       short end = 200;

       long big = 65537;

       long long verybig = 12345678908642;

       printf("un = %u and not %d\n",un, un);

       printf("end = %hd and %d\n",end, end);

       printf("big = %ld and %hd\n",big, big);

       printf("verybig = %lld and not%ld\n", verybig, verybig);

       getchar();

       return 0;

}

/*

数组:数组是按照顺序存储的一系列类型相同的值。整个数组有一个数组名,通过整数下标访问数组中单项或元素。举例:

       float debts[20];

声明debts是一个内含20个元素的数组,每个元素都是可以存储float类型的值。数组的第一个元素是debts[0], 第二个元素是debts[1],以此类推,一直到debts[19]。数组元素的编号是从0开始,不是从1开始。可以给每个元素赋float类型的值。

              比如:可以这么写:

                     debts[5] = 32.54;

                     debts[6] = 1.2e + 21;

       使用数组元素和使用同类型的变量一样。例如,可以这样把值读入到指定的元素中:

              scanf("%f",&debts[4]); // 把一个值读入数组的第五个元素

注意事项:

       debts[20] = 88.32; 该数组元素不存在

       数组的类型可以是任意数据类型, 例如:

              int nannies[22];  //可存储22个int类型整数的数组

              char actors[26];   //可以存储26个字符的数组

              long big[500];             //可以存储500个long类型整数的数组

备注:

       如果char类型的数组末尾包含一个字符串末尾的空字符\0, 则该数组中的内容就构成了一个字符串。

       用于识别数组元素的数字被称为下标、索引或偏移量。下标必须是整数,而且要从0开始计数。数组的元素被依次存储在内存中相邻的位置。

       数组边界。第一个元素的下标是0, 因此循环开始把index设置为0。组后一个元素下标是SIZE - 1。

*/

#define_CRT_SECURE_NO_WARNINGS

#include<stdio.h>

doublepower(double n, int p);  //ANSI函数原型

intmain(void)

{

       double x, xpow;

       int exp;

       printf("Enter a number and thepositive integer power");

       printf(" to which\nthe number willbe raised. Enter q");

       printf("  to quit.\n");

       while (scanf("%1f %d", &x,&exp) == 2)

       {

              xpow = power(x, exp);  //函数调用

              printf("%.3g to the power %dis %.5g\n", x, exp, xpow);

              printf("Enter next pairof  numbers or q to quit.\n");

       }

       printf("Hope you enjoyed this powertrip -- bye!\n");

       return 0;

}

doublepower(double n, int p)  //函数定义

{

       double pow = 1;

       int i;

       for (i = 1; i <= p; i++)

              pow *= n;

       return pow;  //返回pow的值

}

/*

使用函数的三个步骤:

       1.通过函数原型声明函数;2.在程序中通过函数调用使用函数;3.定义函数。

注:

       函数原型是为了方便编译器查看程序中使用的函数是否正确函数定义描述了函数如何工作。现代变成习惯是把程序要素分为接口部分和实现部分,例如本例中的函数原型和函数定义。

       接口部分描述了如何使用一个特性,也就是函数原型所做;实现部分描述了具体行为,这正是函数定义所做的。

*/

#include<stdio.h>

#defineNAME "GIGATHINK,  INC"

#defineADDRESS "101 Megabuck Plaza"

#definePLACE "Megapolis, CA 94904"

#defineWIDTH 40

voidstarbar(void); //函数原型:告诉编译器函数starbar()的类型

intmain(void)

{

       starbar(); //函数调用:表明在次出执行函数

       printf("%s\n", NAME);

       printf("%s\n", ADDRESS);

       printf("%s\n", PLACE);

       starbar();  //使用函数

       return 0;

}

voidstarbar(void) //定义函数:明确指定了函数要做什么

{

       int count;

       for (count = 1; count <= WIDTH;count++)

              putchar("*");

       putchar("\n");

}

/*

       void starbar(void);

       圆括号表明starbar是一个函数名。

       第一个void是函数类型,void类型表明函数没有返回值。第二个void(在圆括号中)表明该函数不带参数。分号表明这是在声明函数,不是定义函数。这行声明了程序将使用一个名为starbar()、没有返回值、没有参数的函数,并且告诉编译器在别处查找该函数的定义。

一般来讲,函数原型指明了函数的返回值类型和函数接受的参数类型。这些信息称为该函数的签名。在本例当中,其签名是该函数没有返回值,没有参数。

       starbar();这是调用void类型函数的一种形式。当计算机执行到starbar();语句时, 会找到该函数的定义并执行其中的内容。执行完starbar()中的代码以后,计算机返回主调函数继续执行下一行,本例中,主调函数是main()。

       starbar()函数中的变量count是局部变量,意思是该变量只属于starbar()函数。

可以在程序的其它地方使用count,这不会引起名称冲突,他们是同名的不同变量。starbar()不需要与主调函数通信。

*/

#include<stdio.h>

#include<string.h>

#defineNAME "GIGATHINK, INC."

#defineADDRESS "101 Megabuck Plaza"

#definePLACE "Megapolis, CA 94904"

#defineWIDTH 40

#defineSPACE ' '

voidshow_n_char(char ch, int num);

intmain(void)

{

       int spaces;

       show_n_char('*', WIDTH);  //用符号常量作为参数

       putchar('\n');

       show_n_char(SPACE, 12);   //用符号常量作为参数

       printf("%s\n", NAME);

       spaces = (WIDTH - strlen(ADDRESS)) / 2;//计算要跳过多少个空格

       show_n_char(SPACE, spaces);  //用一个变量作为参数

       printf("%s\n", ADDRESS);

       show_n_char(SPACE, (WIDTH -strlen(PLACE)) / 2);

       printf("%s\n", PLACE);  //用一个表达式作为参数

       show_n_char('*', WIDTH);

       putchar('\n');

       return 0;

}

/*show_n_char()函数的定义*/

voidshow_n_char(char ch, int num)

{

       int count;

       for (count = 1; count <= num; count++)

              putchar(ch);

}

/*

       void show_n_char(char ch, int num)

       该行告知编译器show_n_char()使用两个参数ch和num, ch是char类型,num是int类型。

       这两个变量被称为形式参数(formalparameter),简称形参。

       形式参数也是局部变量,属于该函数私有。

       在其它函数中使用同名变量不会引起冲突。

       每次调用函数,就会给这些变量赋值。

       注意事项ANSI C要求每个变量前面都声明其类型。

       show_n_char()接受来自main()的值,但是没有返回值。因此,show_n_char()的类型是void。

       在使用函数之前,要用ANSI C形式声明函数原型:

       void show_n_char(char ch, int num);

       当函数接受参数时,函数原型用逗号分隔的列表指明参数的数量和类型。可以省略变量名。

       void show_n_char(char, int);

       在原型中使用变量并没有实际创建变量,char仅仅代表了一个char类型的变量,以此类推。

       在函数调用中,实际参数(actualargument,简称实参)提供了ch和num的值。

例如:show_n_char(SPACE, 12);

       实际参数是空格字符和12。这两个值被赋给show_n_char()中相应的形式参数:变量ch和num。简而言之,形式参数是被调函数中的变量,实际参数是主调函数赋给被调函数的具体值。

       实际参数可以是常量、变量,或甚至是更复杂的表达式。无论实际参数是何种形式都要被求值,然后该值被考唄给被调函数相应的形式参数。

       例如:show_n_char(SPACE,(WIDTH - strlen(PLACE)) / 2);

       构成该函数第二个实际参数是一个很长的表达式,该表达式的值为10。然后10被赋给变量num。

       特别声明:实际参数是具体的值,该值要被赋给作为形式参数的变量。

       因为被调函数使用的值是从主调函数中考唄而来,所以无论对考唄数据进行什么操作,都不会影响主调函数中的原始数据。

       注意:实际参数和形式参数。

       形式参数是函数定义的函数头中声明的变量;实际参数是出现在函数调用圆括号中的表达式.调用函数时,创建了声明为形式参数的变量并初始化为实际参数的求值结果。在本程序中,‘*’和WIDTH都是第一次调用show_n_char()时的实际参数;而SPACE和11是第二次调用show_n_char()时的实际参数。在函数定义中,ch和num都是该函数的形式参数。

*/

#define_CRT_SECURE_NO_WARNINGS

#include<stdio.h>

intimin(int, int);

intmain(void)

{

       int evil1, evil2;

       printf("Enter a pair of integers (qto quit):\n");

       while (scanf("%d  %d", &evil1, &evil2) == 2)

       {

              printf("The lesser of %d and%d is %d.\n", evil1, evil2, imin(evil1, evil2));

              printf("Enter a pair ofintegers (q to quit):\n");

       }

       printf("Bye.\n");

       return 0;

}

intimin(int n, int m)

{

       int min;

       if (n < m)

              min = n;

       else

              min = m;

       return min;   //关键字return后面的表达式的值就是函数的返回值。

}

/*

       因为min是int类型的变量,所以imin()函数的类型也是int。

       变量min属于imin()函数私有,return语句把min的值传回了主调函数。

       lesser = imin(n, m);

       需要再次强调:

              imin()中的变量是imin()的局部变量。

       返回值不仅可以赋给便来那个,也可以被用作表达式是的一部分。举例如下:

              answer = 2 * imin(z, zstar) + 25;

              printf("%d\n", imin(-32+ answer, LIMIT));

       返回值不一定是变量的值,也可以是任意表达式的值。举例如下:

              imin(int n, int m)

              {

                     return (n < m) ? n : m;

              }

       条件表达式的值是n和m中的较小者,该值要返回给主调函数。

       如果函数返回值的类型与函数声明的类型不匹配,那么实际得到的返回值相当于把函数中指定的返回值赋给函数类型相同的变量所得的值。

       return语句的另一个作用是,终止函数并把控制返回给主调函数的下一条语句。举例如下:

              imin(int n , int m)

              {

                     if ( n < m )

                            return n;

                     else

                            return m;

              }

       再举例:

              imin(int n, int m)

              {

                     if ( n < m )

                            return n;

                     else

                            return m;

                     printf("ProfessorFleppard is like totally a fopdoodle.\n");

              }

              声明函数必须声明函数的类型。

              带返回值的函数类型应该与其返回值类型相同;

              而没有返回值类型的函数应该声明为void类型。

              类型声明是函数定义的一部分。

              强调:函数类型指的是返回值的类型,不是函数参数的类型。

              举例:

                     double klink(int a, int b)

              函数头定义了一个带两个int类型参数的函数,但其返回值是double类型。

              函数的前置声明可以放在任意位置。但是,函数原型声明都在使用函数之前。

              stdio.h头文件包含了标准I/O库函数的声明;

              math.h头文件包含了各种数学函数的声明。

              例如:

                     double sqrt(double);

       告知编译器sqrt()函数有一个double类型的形参,而且返回double类型的值。

       不要混淆函数的声明和定义。

声明是告知编译器函数的类型;

       定义是提供实际的代码。

*/

#include<stdio.h>

voidinterchange(int *u, int *v);

intmain(void)

{

       int x = 5, y = 10;

       printf("Originally x = %d and y =%d.\n", x, y);

       interchange(&x, &y);  //把地址发给函数

       printf("Now x = %d and y =%d.\n", x, y);

       return 0;

}

voidinterchange(int * u, int * v)

{

       int temp;

       temp = *u;

       *u = *v;

       *v = temp;

}

/*

       指针:指针是一个值为内存地址的变量(或者叫做数据对象)。

       即指针变量的值是地址。

       ptr = &pooh; 

       该条语句的含义是把pooh的地址赋给ptr。可以说ptr指向pooh。ptr和&pooh的区别是ptr是变量,而&pooh是常量。或者说ptr是可以修改的左值,而&hoop是右值。也可以把ptr指向别处:ptr = &bah; //把ptr指向bah,而不是hoop,现在ptr的值是bah的地址。

       要创建指针变量,先要声明指针变量的类型。

       间接运算符: (*)

       假设ptr指向bah,如下所示:ptr =&bah;

       使用间接运算符* 找出存储在bah中的值,该运算符有时候也被称为解引用运算符。

       val = *ptr;  //找出ptr指向的值

       ptr = &bah;和val = *ptr; 放在一起等于 val =bah;

       与指针有关的运算符:

       1.地址运算符: &

              注解:后跟一个变量时,&给出变量的地址。

              举例:&nurse表示变量nurse的地址;

       2.地址运算符: *

              注解:后跟一个指针名或者地址时,*给出存储在指针指向地址上的值。

              举例:nurse =22;

                     ptr = &nurse; //指向nurse的指针

                     val = *ptr;            //把ptr指向的地址上的值赋给val

                     最终结果为:val = 22。

       指针声明: 声明指针变量时,必须指定指针所指向变量的类型,因为不同的变量类型占用不同的存储空间,一些指针操作要求知道操作对象的大小。另外,程序必须知道储存在指定地址上的数据类型。

指针声明示例:

       int * pi; //pi是指向int类型变量的指针

       char * pc;     //pc是指向char类型变量的指针。

       float * pf, *pg;    //pf、pg都是指向float类型变量的指针。

       上述语句中,星号(*)表明声明的变量是一个指针。

int *pi;

声明的意思是pi是一个指针,*pi是int类型。

*与指针名之间的空格可有可无。通常在声明时使用空格,引用时省略空格。

       char * pc;

       pc是指向char类型的指针。

pc的值是一个地址。

       指针不是整数类型,一些处理整数的操作不能用于处理指针。

例如:

       不能对两个指针执行相乘的操作,但是整数可以。

       指针是一个新类型,不是整数类型。因此指针使用%p格式的转换说明。

       interchange(&x, &y);

       该函数传递的是x,y的地址,而不是他们的值。

       interchange()原型和定义中的形式参数u和v将把地址作为他们的值。

       因此,应把他们声明为地址。

       void interchange(int * u, int * v);

       x,y均为整数,所以u和v是指向整数的指针。

       temp = *u;

       把x的值储存在temp中。

       u的值是&x,所以u指向x。也就是说*u即可表示x的值。

       temp = u; 

       这样的写错误在于,temp被赋予的是x的地址(u的值就是x的地址),而不是x的值。

       函数要交换的是x和y的值,而不是他们的地址。、

       *u = *v;

       把y的值赋给x。相当于x = y;

       可以把变量相关的两类信息传递给函数。如果这种形式的函数调用,那么传递的是x的值。

·function1(x);

       这种形式要求函数定义中的形式参数必须是一个与x的类型相同的变量:

       int function1(int num)该形式适用于计算或者处理值。

·function2(&x)

       这种形式要求函数定义中的形式参数必须是一个指向正确类型的指针:

int function2(int * ptr);该形式适用于要在被调函数中改变主调函数的变量。

       C没有引用变量。

       变量:名称、地址和值。

       普通变量把值作为基本量,把地址作为通过&运算符获得的派生量,而指针变量把地址作为基本量,把值作为通过*运算符获得的派生量。使用&、*和指针可以操纵地址和地址上的内容。*/

#include<stdio.h>

#defineMONTHS 12

intmain(void)

{

       int days[MONTHS] = { 31, 28, 31, 30, 31,30, 31, 31, 30, 31, 30, 31 };

       int index;

       for (index = 0; index < MONTHS;index++)

              printf("Month %2d has %2ddays.\n", index + 1, days[index]);

       return 0;

}

/*

       数组声明:

       float candy[365];  //内含365个float类型元素的数组

       char code[12];            //内含12个char类型元素的数组

       int status[50];              //内含50个int类型元素的数组

       ......

       方括号[]表明candy、code和status都是数组,方括号中的数字表明数组中的元素个数。

       访问数组中的元素,要通过数组下标数(索引)表示数组中的各个元素。

       元素的编号(下标)从零开始。

       在本例中,使用了常量符号MONTHS表示数组大小。推荐用法。

       要创建只读数组,应该使用const声明和初始化数组,比如:

       cosnt int days[MONTHS] = { 31, 28, 31,30, 31, 30, 31, 31, 30, 31, 30, 31 };

       这样修改之后,程序在运行中就不能修改该数组中的内容。

       一旦声明为const,便不能再给他赋值。

*/

#include<stdio.h

#defineSIZE 4

intmain(void)

{

       int no_data[SIZE];  //数组未初始化

       int i;

       printf("%2s %14s\n",     "i", "no_data[i]");

       for (i = 0; i < SIZE; i++)

              printf("%2d %14d\n", i,no_data[i]);

       return 0;

}

/*

       数组使用前,必须初始化。

       可以把数组创建成不同的存储类别。

*/

#include<stdio.h>

#defineSIZE 4

intmain(void)

{

       int some_data[SIZE] = { 1492, 1066 };

       int i;

       printf("%2s %14s\n","i", "some_data[i]");

       for (i = 0; i < SIZE; i++)

              printf("%2d %14d\n", i, some_data[i]);

       return 0;

}

/*

       当初始化列表中的值少于数组元素个数时,编译器会把剩余的元素都初始化为零。

       反之,则会被编译器视为错误。

*/

#include<stdio.h>

#defineMONTHS 12

intmain(void)

{

       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, days[i]);

       return 0;

}

/*

C99规定:可以在初始化列表中使用带括号的下标知名待初始化的元素;

例如:

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

       第一,如果指定初始化器后面有更多的值,如该例中的初始化列表中的片段:[4] =31,30,31,那么后面这些值将被用于初始化指定元素后面的元素。

       也就是说,在days[4]被初始化为31后,days[5]和days[6]将分别被初始化为30和31。

       第二,如果再次初始化指定的元素,那么最后的初始化将会取代之前的初始化。

       例如,初始化列表开始时把days[1]初始化为28,但是days[1]又被后面的指定初始化[1] = 29初始化为29。

       如果未指定元素大小会怎样?

       int stuff[] = {1, [6] = 23};    //会发生什么?

       int staff[] = {1, [6] = 4, 9, 10}; //会发生什么?

       编译器会把数组的大小设置为足够装得下初始化的值。

       所以,stuff数组有7个元素,编号为0~6;

       而staff数组的元素比stuff数组多两个(即有9个元素)。

*/

#include<stdio.h>

#defineSIZE 4

intmain(void)

{

       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;

}

/*

       sizeof表达式被视为整型常量,但是(与C++不同)const值不是。

       表达式的值必须大于0。

       C99支持变长数组,或者简称VLA(C11把这种行为设定为可选,非必备特性)。

       例如:

              float a8[n];

              float a9[m];

*/

#include<stdio.h>

#defineMONTHS 12

intmain(void)

{

       int days[MONTHS] = { 31, 28, 31, 30, 31,30, 31, 31, 90, 31, 30, 31 };

       int index;

       for (index = 0; index < MONTHS;index++)

              printf("Month %2d has %ddays.\n", index + 1, *(days + index)); //与days[index]相同

       return 0;

}

/*

       days是数组首元素的地址,days +index是元素days[index]的地址,而*(days +index)则是该元素的值,相当于days[index]。for循环依次引用数组中的每个元素,并打印每个元素的内容。

*/

#include<stdio.h>

#defineSIZE 10

intsum(int ar[], int n);

intmain(void)

{

       int marbles[SIZE] = { 20, 10, 5, 39, 4,16, 19, 26, 31, 20 };

       long answer;

       answer = sum(marbles, SIZE);

       printf("The total number of marbersis %ld.\n", answer);

       printf("The size of marbles is %zdbytes.\n", sizeof marbles);

       return 0;

}

intsum(int ar[], int n)   //数组的大小是多少?

{

       int i;

       int total = 0;

       for (i = 0; i < n; i++)

              total += ar[i];

       printf("The size of ar is %zdbytes.\n", sizeof ar);

       return total;

}

/*

       marbles的大小 = 10个int类型 * 每个值占4个字节;

       ar占8个字节。ar不是数组本身,他是一个指向marbles数组首元素的指针。由于系统使使用8字节储存地址,所以指针变量的大小是8字节。

       综上所述:marbles是一个数组,ar是一个指向marbles数组首元素的指针利用C中数组和指针的特殊关系,可以用数组表示法来表示指针。

*/

#include<stdio.h>

intdata[2] = { 100, 200 };

intmoredata[2] = { 300, 400 };

intmain(void)

{

       int * p1, *p2, *p3;

       p1 = p2 = data;

       p3 = moredata;

 

       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;

}

/*

              C语言,ar[i]和*(ar+1)这两个表达式都是等价的。无论ar是数组名还是指针变量,这两个表达式都没问题。但是,只有当ar是指针变量时,才能使用ar++这样的表达式。

*/


猜你喜欢

转载自blog.csdn.net/qq_20440225/article/details/79841062
今日推荐