C语言学习8:malloc返回的void*类型指针不可以做更改,free双重释放,二维数组的初始化和打印,a和a[0]和a[0][0]的区别,数组指针(*p)[3],指针数组*a[10],动态内存分配版约瑟夫环,动态分配版去空格和逗号处理,二级指针与二维数组互用
1,malloc返回的void *类型指针不可做更改
#include <stdio.h> #include <stdlib.h> int main(void) { int *p=malloc(20); p++; //p已经变化过,因此是 无效的释放 free(p); return 0; }
结果:报错
*** Error in `./a.out': free(): invalid pointer: 0x0156000c *** Aborted (core dumped)
2,free双重释放
#include <stdio.h> #include <stdlib.h> //双重释放,p的值不变,但是系统报警告: int main(void) { int *p=malloc(32); printf("p=%p\n",p); free(p); printf("====================\n"); printf("p=%p\n",p); //double free free(p); return 0; }
结果:
p=0x1238008 ==================== p=0x1238008 *** Error in `./a.out': double free or corruption (fasttop): 0x01238008 *** Aborted (core dumped)
3,二维数组的初始化和打印
#include <stdio.h> //数组的初始化和输出打印形式 int main(void) { int a[2][3] = {3,4,5,6,7,8}; int b[2][3] = {{6,7,8},{9,10,11}}; int c[][3]={[0][2]=16,[1][1]=32}; int i,j; for(i=0;i<2;i++) { for(j=0;j<3;j++) { printf("a[%d][%d] = % 2d ",i,j, *(*(a+i)+j)); } putchar('\n'); } printf("========================\n"); for(i=0;i<6;i++) printf("b[0][%d] = %d\n",i,b[0][i]); printf("=======================\n"); for(i=0;i<2;i++) for(j=0;j<3;j++) { printf("c[%d][%d]=%2d\n",i,j,c[i][j]); } return 0; }
结果:
a[0][0] = 3 a[0][1] = 4 a[0][2] = 5 a[1][0] = 6 a[1][1] = 7 a[1][2] = 8 ======================== b[0][0] = 6 b[0][1] = 7 b[0][2] = 8 b[0][3] = 9 b[0][4] = 10 b[0][5] = 11 ======================= c[0][0]= 0 c[0][1]= 0 c[0][2]=16 c[1][0]= 0 c[1][1]=32 c[1][2]= 0
4,a和a[0],a[0][0]的区别
#include <stdio.h> //a和a[0]和a[0][0]是同一个地址和值,都表示首地址,但是代表的含义不同 int main(void) { int a[2][3]={23,34,67,25,55,99}; printf("sizeof a =%u\n",sizeof a );//代表不同的范围,整个 printf("sizeof a[0]=%u\n",sizeof a[0]);//1行 printf("sizeof a[0][0]=%u\n",sizeof a [0][0]);//二维数组一个元素 printf("-------------------------------\n"); printf("&a=%p\n",&a);//初始地址都是一样的 printf("a=%p\n",a); printf("&a[0]=%p\n",&a[0]); printf("&a[0][0]=%p\n",&a[0][0]); printf("------------------------------\n"); printf("&a+1 =%p\n",&a+1);//整个二维数组+1,就是加上24个字节 printf("-----------------------------\n"); printf("a+1=%p\n",a+1);//这个加12个字节,加一行 printf("&a[0]+1=%p\n",&a[0]+1);//加12个字节 printf("=----------------------------\n"); printf("a[0]+1=%p\n",a[0]+1);//加一个元素4个字节 printf("&a[0][0]+1=%p\n",&a[0][0]+1);//加上一个元素 return 0; }
结果:加了取地址符,
sizeof a =24 sizeof a[0]=12 sizeof a[0][0]=4 ------------------------------- &a=0xbeed3190 a=0xbeed3190 &a[0]=0xbeed3190 &a[0][0]=0xbeed3190 ------------------------------ &a+1 =0xbeed31a8 ----------------------------- a+1=0xbeed319c &a[0]+1=0xbeed319c =---------------------------- a[0]+1=0xbeed3194 &a[0][0]+1=0xbeed3194
5,数组指针
#include <stdio.h> //分析数组指针 void foo(int a[][3],int len) { int i,j; printf("int foo,size of a=%u\n",sizeof a); for(i=0;i<len;i++) { for(j=0;j<3;j++) { printf("a[%d][%d]=%2d\n",i,j,a[i][j]); }//%2d其实是表示列宽为2,其实大了会自动补全 putchar('\n'); } } void bar(int(*p)[3],int len) { int i,j; for(i=0;i<len;i++) { for(j=0;j<3;j++) { printf("p[%d][%d]=%2d\n",i,j,*(*(p+i)+j)); } } } int main(void) { int a[2][3]= {6,7,234,45,754,2}; int (*p)[3]=NULL;//这个是指针数组,存放数据类型是指针 p=a;//所以指针要这么赋值指向 printf("sizeof a=%u,sizeof p=%u\n",sizeof a,sizeof p); int i,j; for(i=0;i<2;i++)//指针数组的打印形式 { for(j=0;j<3;j++) { printf("p[%d][%d]=%2d\n",i,j,*(*(p+i)+j)); } putchar('\n'); } printf("__________________________\n"); foo(a,2); printf("_________________________\n"); bar(a,2); return 0; }
结果:
sizeof a=24,sizeof p=4 p[0][0]= 6 p[0][1]= 7 p[0][2]=234 p[1][0]=45 p[1][1]=754 p[1][2]= 2 __________________________ int foo,size of a=4 a[0][0]= 6 a[0][1]= 7 a[0][2]=234 a[1][0]=45 a[1][1]=754 a[1][2]= 2 _______________________ p[0][0]= 6 p[0][1]= 7 p[0][2]=234 p[1][0]=45 p[1][1]=754 p[1][2]= 2
6,指针数组,
#include <stdio.h> //数值指针 int main(void) { int a[3][4]={ [0][2]=36,[0][3]=48, [1][1]=66,[1][2]=32, [2][2]=88,[2][3]=96, }; int *p[3]={a[0],a[1],a[2]};//数组指针应用方式 int i,j; for(i=0;i<3;i++) { for(j=0;j<4;j++) { printf("p[%d][%d]=%2d",i,j,*(*(p+i)+j)); } putchar('\n'); } printf("==========================\n"); char *sary[3]={ "china unix", "chongqing university", "uplooking" }; for(i=0;i<3;i++) puts(sary[i]); return 0; }
结果:
p[0][0]= 0p[0][1]= 0p[0][2]=36p[0][3]=48 p[1][0]= 0p[1][1]=66p[1][2]=32p[1][3]= 0 p[2][0]= 0p[2][1]= 0p[2][2]=88p[2][3]=96 ========================== china unix chongqing university uplooking
7,约瑟夫环 从M个人中去的N位置的人
#include <stdio.h> #include <stdlib.h> //函数返回指向数组char[8]的指针 char (*alloc_mem(int row))[8] { return malloc(row * sizeof(char) * 8); } void rand_mem(char (*p)[8],int row) { int i; for(i=0;i<row;i++) { //格式化打印 sprintf(p[i],"%c%c%c%c%c%c",rand()%26+'A', rand()%26+'a',rand()%26+'a', rand()%26+'a',rand()%26+'a','\0'); } } void print_name(char (*p)[8],int row) { int i; for(i=0;i<row;i++) { printf("%2d: %s",i+1,p[i]); if((i+1)%4==0) putchar('\n'); } putchar('\n'); } int main(void) { int m,n; char (*pname)[8]; printf("input m&n:"); scanf("%d%d",&m,&n); pname=alloc_mem(m); rand_mem(pname,m); print_name(pname,m); printf("===================\n"); printf("退出序号:\n"); int i,out=m,count=0; while(out>0) { for(i=0;i<m;i++) { // if(pname[i][0]!='\0') 有问题 count++; if(count==n) { printf("%2d:%s\n",i+1,pname[i]); out--; count=0; // pname[i][0]='\0'; 有问题 } } } free(pname); return 0; } //犯过的错误1,没有对这个进行%26出现乱码 //char (*pname)[8];定义指针数组 //我不明白这个pname[i][0]='\0'有什么用,存在反而有问题,待考证的项目
结果:
will@will-laptop:~/ex/7$ ./a.out input m&n:4 3 1: Nwlrb 2: Bmqbh 3: Cdarz 4: Owkky =================== 退出序号: 3:Cdarz 2:Bmqbh 1:Nwlrb 4:Owkky will@will-laptop:~/ex/7$ ./a.out input m&n:6 6 1: Nwlrb 2: Bmqbh 3: Cdarz 4: Owkky 5: Hiddq 6: Scdxr =================== 退出序号: 6:Scdxr 6:Scdxr 6:Scdxr 6:Scdxr 6:Scdxr 6:Scdxr
8.应用到动态内存分配的去掉空格和逗号的处理
#include <stdio.h> #include <stdlib.h> #include <string.h> //输入一个连续带空格的字符串,输出无间隔的字符串 char s[1024]; char *sary[64]; int main(void) { printf("input a string:"); gets(s); int i=0,count=0,j; int word_start,word_len; while(1) { if(s[i]!=' '&&s[i]!=',') { word_start=i; while(s[i]!=' '&&s[i]!=','&&s[i]!='\0') i++; word_len=i-word_start; //计算一个连续字符串的长度 sary[count]=malloc(word_len+1); //分配空间 if(NULL==sary[count]) goto err0; memcpy(sary[count],s+word_start,word_len); //内存交换 sary[count][word_len]='\0'; //最后赋予一个结束符 count++; } if(s[i]=='\0')//判断是否转换完成 break; i++; } printf("----------------------\n"); for(i=0;i<count;i++) printf("%s",sary[i]); for(i=0;i<count;i++) free(sary[i]); return 0; err0: for(j=0;j<i;j++) free(sary[j]); } //出现错误段错误:err0没有处理好,一厢情愿的认为释放count就好,不知道 //count=0的时候无法释放,还有就是第32行没有两个等于,也会出现段错误。 //显示乱码错误:结果是21行少一个等于号
结果:
will@will-laptop:~/ex/7$ gcc 7.8.c 7.8.c: In function ‘main’: 7.8.c:11:2: warning: ‘gets’ is deprecated (declared at /usr/include/stdio.h:638) [-Wdeprecated-declarations] will@will-laptop:~/ex/7$ ./a.out input a string:what your name wo,sn,sn ---------------------- whatyournamewosnsn
9.二级指针与二维数组用法
#include <stdio.h> //二级指针和二维数值是可替换的关系 int main(void) { char *sary[3]={ "china unix", "chongqing university", "uplooking" }; char **p=NULL; p=sary; int i; for(i=0;i<3;i++) puts(p[i]); return 0; }
结果:
will@will-laptop:~/ex/7$ ./a.out china unix chongqing university uplooking