C语言的一些知识总结

这段时间开始自己尝试着写学生信息管理系统,总结一下中间还有上课遇到的一些问题

一、、共用体(union)与大端序小端序

emmmmm先总结一下共用体的主要知识点

1,共用体中的不同元素占用同一内存,既起始地址相同。

2.共用体中内存为最长成员的长度。

3,共用体变量可被赋值给任一成员,但一次只能赋一种值,新值会覆盖旧值。

下面的例子是在网上看到的,还是挺有用的

#include<stdio.h>//
union myun     
{    
struct { int x; int y; int z; }u;     
 char k;     
}a;     
int main()     
{     
 a.u.x =4;    
 a.u.y =5;     
 a.u.z =6;     
 a.k = '0';     
 printf("%d %d %d\n",a.u.x,a.u.y,a.u.z); //输出为48,5,6,因为k的首地址其实就是结构体a的首地址所以x被k=0覆盖,所以蔬菜ascii码
	return 0;    
}    

大小端序

大小端序的使用硬件的话好像跟处理器(cpu)有一定的关系,在这里就不深究。

大端序:高字节放在低地址

小端序:高字节放在高地址

大小端模式对共用体的影响

        共用体一般使用小端序存储,当共用体中有不同类型的变量,用一种变量类型给共用体赋值,但用另一种变量类型读取共用体的时候就涉及到大小端的问题。

在这里放入最近遇到的一道涉及大小端的题

#include<stdio.h>
#include<string.h>
int main()
{
	int i;
	char n[]={1,0,0,0};
	i=strlen(n);//数组n只接收第一个数,当接收0时自动转化为\0所以i=0
	printf("%d\n",i);
	printf("%d",*(int*)n);
	return 0;
}
按小端序存放,按数组来看最左端为最小地址,最左端1为低字节,一个字节占八位,则为00000001,所以输出为1,若1放在数组第二位,则为0000000100000000,所以输出为256.


二、、使用malloc创建一个动态二维数组

malloc创建的内存存放于堆上,有用户自己创建和释放,若创建成功返回地址指针,否则返回空指针。

#include<stdio.h>
#include<stdlib.h>
int main(void){
	int **a;
	int r,c;
	scanf("%d %d",&r,&c);//行,列。 
	a=(int**)malloc(r*sizeof(int*));//a是一个二级指针创建了存取r*一级指针所占空间  
	for(int i=0;i<r;i++){  
        a[i]=(int*)malloc(c*sizeof(int));//a[i]是一个一级指针在每一行都给划分出了存储列数所需空间  
    } 
	for(int i=0;i<r;i++){  
        for(int j=0;j<c;j++){   
            scanf("%d",&a[i][j]);  
        }  
    }  
   for(int i=0;i<r;i++){  
        for(int j=0;j<c;j++){  
            printf("%d\t",a[i][j]);  
        }  
        printf("\n");  
    }  
}

其实通过这串代码可以看出二维数组本质上也是一个一维数组,如a[1][3]=a+(1*行数)+3////i*行+j;

3.递归算法---汉诺塔问题。

说实话,递归本身很好理解,它可以把很复杂的功能用及其简单的代码来实现,但其各层嵌套却容易将人绕晕,理清其中的思维是一件相当考验智力和耐心的事情。

汉诺塔这道题本身在课本上有,个人浅显的认为将盘子简化到2个,emmmm,然后倒推回去较为好理解

#include<stdio.h>
void hanoi(int n,char x,char y,char z){
	if(1==n)	printf("%c->%c\n",x,z);//当只有一个盘时,直接1->3 
	else{
		hanoi(n-1,x,z,y);//1,1,3,2
		printf("%c->%c\n",x,z);//此时x,y,z仍为1,2,3输出1->3 
		hanoi(n-1,y,x,z);//1,2,1,3
	}
}
int main(void){
	int m;
	scanf("%d",&m);
	hanoi(m,'1','2','3');//m=2,输出为1->2 // 1->3 // 2->3 
}

4--1,调用函数时值的传递

#include<stdio.h>
void swap(int *a,int *b){ 
	*a=*a+*b;
	*b=*a-*b;
	*a=*a-*b;
}
int main(void){
	int a=3,b=5;
	swap(&a,&b);
	printf("%d %d",a,b);
}

函数之间的传递为值的传递,通过地址调用可以看做在形参和实参之间在搭建了一座桥梁对实参的值进行操作。

5,自增运算符

最近遇到的一道题目

#include<stdio.h> 
#include<string.h>
int main(void){
	int a=3,b=0;  
	b=(++a)+(++a)+(++a);
	printf("%d %d\n",a,b);
	}
答案为6,16,由于运算符/+/具有左结合性,故(++a)+(++a)先结合,所以为10,后再结合a=6,所以b=16

6.指向结构体的指针变量中运算符的优先级

 
 
#include<stdio.h>
typedef struct node{
	int a; 
}stu;
int main(void)
{
	stu n[2]={1,10};
	stu *p;
	p=n;
	//printf("%d\n",p->a++);
	//printf("%d\n",(p++)->a);
	//printf("%d\n",++p->a);
	//printf("%d\n",(++p)->a);
}
注:只要牢记->,'.','()'的运算符优先级最大,这道题就不难做

猜你喜欢

转载自blog.csdn.net/printfxgd/article/details/80339766