标签:浮点型 fir 问题 ati 判断 如何使用 随机 average 整数
//指针 /* C语言的指针简单又有趣,通过指针,可以简化一些C编程任务的执行,还有一些任务, 如动态内存的分配,没有指针是无法执行的。所以对于C语言,学习指针是非常有必要的。 在介绍指针之前,前面已经多次出现指针的概念了。 也正如前面所讲的,每一个变量都有一个内存位置,每一个内存位置都定义了可使用&访问内存的地址, 它代表了内存中的一个地址 */ //举个栗子 #include <stdio.h> int main01() { int var1; int var2[10]; printf("var1的变量地址:%p\n", &var1); //var1的变量地址:0061FF2C printf("var2的变量地址:%p\n", &var2); //var2的变量地址:0061FF04 return 0; } //什么是指针? /* 指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。 就像其他变量或者常量一样,必须在使用指针储存其他变量地址之前,对指针进行声明, 声明指针的形式和声明变量的形式比较类似,type *var-name,就是在变量之前加上一个*, 举个例子: int *ip; 一个整型的指针 double *dp; 一个 double 型的指针 float *fp; 一个浮点型的指针 char *ch; 一个字符型的指针 正所谓指针也是需要空间来进行存储的,也需要有一个变量来指向它,这个变量叫做指针变量。 指针变量 int *p=&a; 整形变量int a=1;等等性质都是一样的,都是一个变量指向一个值。 只不过p指向的变量是一个指针类型,所以叫做指针变量,指针变量指向的是一个指针, 通过加上*那么可以找到指针指向的值。 那么这个指针变量同样需要空间来进行存储,对于指针来说无论它指向的值有多大,占多少空间, 对于指针本身来说,长度永远是固定的,对于相同位数的机器来说,一般只占4个字节。 并且是一个十六进制数,因此指针之间是比较类似的,可能不同的就是所指向的值不一样。 这里插一句: 对于python来说,其列表按照索引查询的时间复杂度为o(1),并且不随着元素的增大而有所变化。 这是为什么呢?因为python的列表是采用元素外置的方法,也就是说列表里面存储的不是元素本身, 而是元素的指针,不管元素的值多大,其指针的大小是固定的,是4个字节, 而列表又是一块连续的存储空间,通过首地址加上索引,可以瞬间计算出指针的偏移量, 从而找到相应的元素的指针,在打印的时候会自动打印指针所指向的值。 所以时间复杂度才为o(1),可见学习C语言对理解python还是很有帮助的,因为在py里, 指针这种概念被高度封装起来,并不是摒弃掉,python里面大量用到了指针的概念,只不过我们接触不到罢了, 但是学习指针,对了解python内部的数据结构是非常有帮助的。 */ //如何使用指针 /* 定义一个指针 int *p; 获取指针指向的值*p, 定义一个int变量,int a=1; 获取a的地址&a 把指针赋值给指针变量 p = &a */ int main02() { int var=20; //声明一个变量 int *p; //声明一个指针 p = &var; //在指针变量p中储存var的地址 printf("var=%d,also=%d\n",var, *p); //var=20,also=20 printf("address of var=%p,also=%p\n", &var,p); //address of var=0061FF28,also=0061FF28 return 0; } //C中的NULL指针 /* 在指针变量的声明时,如果没有确切的地址可以赋值,那么最好为指针赋值为NULL。 指针为NULL的话,表名这是一个空指针,NULL指针是一个定义在标准库中值为0的常量 */ //举个栗子 int main03() { int *p=NULL; printf("address of p=%p\n",p); //address of p=00000000 return 0; } /* 在大多数的操作系统上,程序不允许访问地址为0的内存,因为该内存是为操作系统保留的。 内存地址0有特别重要的意义,它表明该指针指向一个不可访问的内存位置。 如果想判断一个指针是不是空指针可以使用if语句 if(p) */ //指针的算数运算 /* C 指针是一个用数值表示的地址。因此可以对指针执行算术运算。可以对指针进行四种算术运算:++、--、+、-。 假设 ptr 是一个指向地址1000的整型指针,是一个32位的整数,让我们对该指针执行下列的算术运算: ptr++ 在执行完上述的运算之后,ptr 将指向位置 1004,因为 ptr 每增加一次, 它都将指向下一个整数位置,即当前位置往后移 4 个字节. 这个运算会在不影响内存位置中实际值的情况下,移动指针到下一个内存位置。 如果 ptr 指向一个地址为 1000 的字符,上面的运算会导致指针指向位置 1001,因为下一个字符位置是在 1001。 */ //递增一个指针 /* 我们喜欢在程序中使用指针代替数组,因为变量指针可以递增,而数组不能递增,因为数组是一个常量指针。 下面的程序递增变量指针,以便顺序访问数组中的每一个元素: */ const int max=3; int main04() { int var[]={11,22,33}; int i,*ptr; //指针指向数组地址 ptr = var;//可以是var也可以是&var,也可以是&var[0],反正都是首元素的地址 for (i=0;i<max;i++) { printf("store position:var[%d]=%x\n",i,ptr); printf("store value:var[%d]=%d\n",i,*ptr); //移动下一个位置 ptr++; } /* store position:var[0]=0061FF1C store value:var[0]=11 store position:var[1]=0061FF20 store value:var[1]=22 store position:var[2]=0061FF24 store value:var[2]=33 */ } //递减一个指针 int main05() { int var[]={11,22,33,44}; int i,*ptr; ptr = (var+3); for (i=sizeof(var)/sizeof(var[0])-1;i>=0;i--) { printf("store address:var[%d]=%x\n", i,ptr); printf("store value:var[%d]=%d\n",i, *ptr); ptr--; } /* store address:var[3]=61ff24 store value:var[3]=44 store address:var[2]=61ff20 store value:var[2]=33 store address:var[1]=61ff1c store value:var[1]=22 store address:var[0]=61ff18 store value:var[0]=11 */ } //指针数组 int main06() { int var[]={11,22,33}; int i; for (i=0;i<3;i++) { printf("value of var[%d]=%d\n",i,var[i]); } /* value of var[0]=11 value of var[1]=22 value of var[2]=33 */ return 0; } const int num=4; int main07(){ int var[]={11,22,33,44}; int i,*ptr[num];//声明一个指针数组,里面有4个元素都是指针类型 for (i=0;i<num;i++) { ptr[i]=&var[i];//每一个var里面每一个元素的指针都复制个ptr里面的指针变量 } for (i=0;i<num;i++) { printf("var[%d]=%d,also=%d\n",i,var[i],*ptr[i]); } return 0; /* var[0]=11,also=11 var[1]=22,also=22 var[2]=33,also=33 var[3]=44,also=44 */ } //也可以用一个指向字符的指针数组来存储一个字符串列表 int main08() { const char *name[]={ "satori", "mashiro", "nagisa", "matsuri" }; char s[10]; int i; for (i=0;i<4;i++) { printf("value of name[%d]=%s\n",i,name[i]); //之前也说过,数组的地址就是首元素的地址 printf("first element address=%p,but !=%p,also=%p\n",name[i],&name[i],&(name[i][0])); /* value of name[0]=satori first element address=00405148,but !=0061FF1C,also=00405148 value of name[1]=mashiro first element address=0040514F,but !=0061FF20,also=0040514F value of name[2]=nagisa first element address=00405157,but !=0061FF24,also=00405157 value of name[3]=matsuri first element address=0040515E,but !=0061FF28,also=0040515E */ //关于name[i]为什么不等于&name[i] //因为name是一个指针数组,那么name[i]获取到的仍然一个指针,指向了相应的字符串的首元素 //我们直接按照字符串格式打印是没问题的,打印的就是整个字符串 //当做指针打印也是没问题的,打印的是首元素的地址,至于为什么&name[i]不行, //还记得之前说的对于指向数组的指针来说str和*str是不一样的吗? //因为str已经是一个指针了,所以不能再使用&了 //但对于char str[]="xxx"来说,因为str不是指向字符数组的指针, 而是一个字符数组 //所以以以指针打印&str是没问题的,获取的就是首元素的地址 //对于以指针形式打印str,也会自动打印首元素的地址。 //因此打印首元素的地址,对于字符数组来说,str和&str是一样。 //但是对于指向字符数组的指针来说,str和&str是不一样的。 //但是把指向数组的指针当成数组来用的话,就举上面的例子&(name[i][0])和name[i]是一样的 //因为name[i]虽然是地址,但是name[i][0]依旧可以获取首元素,再加上&也是可以的 } } //指向指针的指针 /* 指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。 通常,一个指针包含一个变量的地址。 当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。 pointer pointer variable address address value 一个指向指针的指针变量必须如下声明,即在变量名前放置两个星号。例如,下面声明了一个指向 int 类型指针的指针: int **var; 当一个目标值被一个指针间接指向到另一个指针时,访问这个值需要使用两个星号运算符,如下面实例所示: */ int main09() { int var; int *ptr; int **pptr; var=3000; //获取var的地址 ptr=&var; pptr=&ptr; //使用pptr获取值 printf("value of var=%d,also=%d,also=%d\n",var,*ptr,**pptr);//value of var=3000,also=3000,also=3000 return 0; } //传递指针给函数 /* C语言允许传递指针个函数,只需声明函数类型为指针即可*/ #include <time.h> void getSecond(unsigned long *sec); int main10() { unsigned long sec; //定义一个无符号长整型,然后将指针传递给函数 //这样指针便指向了所在的内存,然后只要修改指针所指向的值 //就可以进行修改,这在python里面是做不到的,因为在py里会指向一个新值,不会修改原来的 getSecond(&sec); //输出实际值 printf("Number of seconds=%d\n",sec); //Number of seconds=1534338344 return 0; } void getSecond(unsigned long *sec) { //获取当前的秒数 *sec = time(NULL); return; } //在学C之前,有人说C难学,尤其是学到指针的时候,指针和数组之间的关系不晕才怪 //表示自己在学的时候,没感觉到,虽然在反复强调, 现在回想一下,是有些相似哈。 //指针可以指向数组的第一个元素的地址,从而当做数组打印所有元素 //而数组本身的地址又是首元素的地址,所以两者确实是比较相似的 //那么函数的参数是指针类型的话, 除了接收指针,也可以接收数组 double getAvg(int *arr, int size); int main11() { int arr[]={11,22,33,44,55};//带有5个元素的数组 double avg1, avg2,avg3; //传递一个指向数组的指针作为函数的参数 //我们的getAvg显然第一个参数要是指针类型,那么这里我们传入arr,&arr,&arr[0]都是一样的 avg1 = getAvg(arr,5); avg2 = getAvg(arr,5); avg3 = getAvg(arr,5); //输出返回值 printf("average of arr=%f,also=%f,also=%f\n",avg1,avg2,avg3); //average of arr=33.000000,also=33.000000,also=33.000000 } double getAvg(int *arr,int size) { int i; int sum=0; double avg; for(i=0;i<size;i++) { sum += arr[i]; } avg = (double)sum / size; return avg; } //从函数返回指针 /* 函数不支持返回一个数组,但是可以返回一个指向数组的指针,我们知道,返回数组的指针 就等于是返回数组了,反正指针也可以实现数组的功能,当成数组来用,访问数组的每一个值 所以说指针和数组比较相似,但不至于晕, 但是注意的是,指针也不能够直接返回,必须定义static */ //由于我们返回的是指针,所以这里必须要加上星号, //如果不加,表示返回一个整型,加上*表示返回一个指针 int *getRandom() { //必须定义static static int r[10]; int i; srand((unsigned)time(NULL));//设置随机种子 for (i=0;i<10;i++) { r[i]=rand(); printf("r[%d]=%d\n",i ,r[i]); } return r; } int main12() { int *p;//定义一个指针 int i; p = getRandom(); for (i=0;i<10;i++) { //p是数组首元素的指针,既可以通过*(p+i)访问,也可以当成数组通过p[i]的方式来访问 printf("*(p+%d)=%d,also=%d\n",i,*(p+i), p[i]); } } /* r[0]=18171 r[1]=23618 r[2]=17990 r[3]=13924 r[4]=6267 r[5]=25621 r[6]=20508 r[7]=29240 r[8]=8512 r[9]=15428 *(p+0)=18171,also=18171 *(p+1)=23618,also=23618 *(p+2)=17990,also=17990 *(p+3)=13924,also=13924 *(p+4)=6267,also=6267 *(p+5)=25621,also=25621 *(p+6)=20508,also=20508 *(p+7)=29240,also=29240 *(p+8)=8512,also=8512 *(p+9)=15428,also=15428 */ /* 关于c不能返回指针,而定义了static就能返回了呢? 首先,指针必须要指向一块合法的内存,比方我随便定义一个指针,指向一块内存 int *p=0xffff;这显然是不合法的,因为0xffff是我瞎几把定义的,没有指向一个合法的值, 当然我们定义这个指针本身是没有问题,可以随便的赋值,随便的玩耍,但是当我们使用*p的时候, 那么就会去操作p这个指针指向的内存,而访问的内存必须是已经向操作系统申请完毕的内存, 显然我们这里没有申请,便直接访问了,这是不允许的,因此在某些编译器上便会出现段错误。 我们这里也是一样的道理,当我们返回一个指针,这个指针本来是指向一块合法的内存空间, 但是当函数执行完毕之后,那么里面所有的局部变量就都被释放了,原本指向的内存,已经被操作系统回收了。 那么当我们再main中再次访问的时候,那片内存空间已经不再是我们可以涉及的领域了。 因此也就变成了野指针,野指针指的就是指向了不合法地址的指针。 那么为什么加上static就能返回了呢?因为局部变量是储存在内存的栈区,函数执行完毕, 局部变量所占的内存便被释放了,函数内的变量不再拥有那个内存地址,所以不能返回指针, 但是当我们加上了static之后,那么变量的值就会存储在内存中的静态数据区,不会随着函数的执行结束而被清除, 故能返回其地址 */ //笔记 /* 指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。 在使用指针存储其他变量地址之前,对其进行声明。 要理解指针就要先理解计算机的内存。计算机内存会被划分为按顺序编号的内存单元。 每个变量都是存储在内存单元中的,称之为地址。 并且内存地址是按照字节划分的,一个字节对应一个地址,所以说int类型占4个字节, 所以会用四个地址。 */ int main13() { int var=20;//实际变量的声明,此时var这个变量是存在内存地址的,地址对应某个内存单元,该单元存储了数据20 int *p; //定义了一个指针,即一个内存单元的地址变量 p = &var;//这指针变量中存储var的地址,就是将地址赋给了这个指针变量; printf("value=%d\n",*p);//利用指针指向的内存输出值 printf("addr=%p,also=%p\n",p,&var);//用p直接输出地址值,因为存储的就是地址的值 /* value=20 addr=0061FF28,also=0061FF28 */ } //指针的一些说明 /* int p;这是一个普通的整型变量 int *p;首先p与*结合,说明p是一个指针,然后与int结合,说明指针指向的是一个整型元素 int p[3];首先p与[]结合说明p是一个数组,然后与int结合说明p是一个整型数组,整体就是整形数组的第4个元素 int *p[3];首先p与[]结合,因为优先级比*高,说明是一个数组,然后与*结合,说明数组里面的每一个元素 都是一个指针类型,在与int结合,说明指针指向的是一个整型 int **p;p与*结合,说明p是一个指针,再与*结合,说明p是一个指向指针的指针,再与int结合,说明*p指向的 是一个整型 int p(int);从 p 处起,先与 () 结合, 说明 p 是一个函数, 然后进入 () 里分析, 说明该函数有一个整型变量的参数, 然后再与外面的 int 结合, 说明函数的返回值是一个整型数据。 int (*p)(int);从 p 处开始, 先与指针结合, 说明 p 是一个指针, 然后与()结合, 说明指针指向的是一个函数 然后再与()里的 int 结合, 说明函数有一个int 型的参数 再与最外层的 int 结合, 说明函数的返回类型是整型, 所以 p 是一个指向有一个整型参数且返回类型为整型的函数的指针。 */
标签:浮点型 fir 问题 ati 判断 如何使用 随机 average 整数
原文地址:https://www.cnblogs.com/traditional/p/9484501.html