函数例题、C语言指针内容

尽可能用函数实现!

1.定义长度为10的数组
	输入9个数字
	然后:随机生成一个100以内的数字 
	把随机生成的这个数字插入到数组中,使数组保持有序
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

void sort(int arr[],int len){
	int i,j;
	for(i=0;i<len-1;i++){
		int min = i;//最小数下标
		for(j=i+1;j<=len-1;j++){
			if(arr[min]>arr[j]){
				min = j;
			}
		}
		if(min != i){
			int t = arr[min];
			arr[min] = arr[i];
			arr[i] = t;
		}
	}
}

int main(){
	srand(time(NULL));
	int n = rand()%100;
	int i;
	int arr[10] = {0};
	arr[9] = n;
	int len = sizeof(arr)/sizeof(arr[0]);
	for(i=0;i<len-1;i++){
		printf("请输入第%d个数字:",i+1);
		scanf("%d",&arr[i]);
		printf("\n");
	}
	sort(arr,len);
	for(i=0;i<=len-1;i++){
		printf("%d ",arr[i]);
	}
	return 0;
}


2.输入第一个数组长度
	并依次从小到大有序输入这个数组的元素
  输入第二个数组长度
	并依次从小到大有序输入这个数组的元素
  把上面两个有序数组中的元素合并到第三个数组中,使数组依然有序
#include<stdio.h>

void readarr(int arr[],int len){
	printf("请从小到大输入%d个元素:",len);
	int i;
	for(i=0;i<len;i++){
		scanf("%d",&arr[i]);
	}
}
//arr升序,brr升序,合并放到crr
void mergerasc(int arr[],int len1,int brr[],int len2,int crr[]){
	int i=0,j=0,k=0;
	while(i<len1 && j<len2){
		if(arr[i]<brr[j]){
			crr[k++] = arr[i++];//因为k++是后操作
			//k++
			//i++
		}else{
			crr[k++]=brr[j++];
			//k++
			//i++;
		}
	}
	//arr,brr 有一个数组已经无元素,剩下直接放
	while(i<len1){//剩下arr
		crr[k++]=arr[i++];
	}
	while(j<len2){//剩下brr
	crr[k++]=brr[j++];
	}	
}
void showarr(int arr[],int len){
	int i;
	for(i=0;i<len;i++){
		printf("%d ",arr[i]);
	}
	printf("\n");
}
int main(){
	printf("请输入第一个数组的长度:");
	int len1;
	scanf("%d",&len1);
	int arr[len1];
	readarr(arr,len1);
	printf("请输入第二个数组的长度:");
	int len2;
	scanf("%d",&len2);
	int brr[len2];
	readarr(brr,len2);
	int crr[len1+len2];
	mergerasc(arr,len1,brr,len2,crr);
	showarr(crr,len1+len2);
	return 0;
}
//或者
#include<stdio.h>


void myscanf(int *arr,int len){
	int i;
	printf("请输入%d个数字",len);
	for(i=0;i<len;i++){
		scanf("%d",&arr[i]);
	}
}

void mysort(int *arr,int len){
	int i;
	int j;
	for(i=0;i<len;i++){
		int min=i;
		for(j=i+1;j<len;j++){
			if(arr[min]>arr[j]){
				min=j;
			}
		}
		if(min!=i){
			int t=arr[i];
			arr[i]=arr[min];
			arr[min]=t;
		}
	}
}

void mergerasc(int *arr,int len1,int *brr,int len2,int *crr){
	int i;
	int j=0;
	for(i=0;i<len1;i++){
		crr[j++]=arr[i];
	}			
	for(i=0;i<len2;i++){
		crr[j++]=brr[i];
	}
}
void show(int *arr,int len){
	int i;
	for(i=0;i<len;i++){
		printf("%d ",arr[i]);
	}
	printf("\n");

}

int main(){
	int i;
	int arr[10];
	int brr[10];
	int crr[20];
	myscanf(arr,10);
	myscanf(brr,10);
	mergerasc(arr,10,brr,10,crr);
	mysort(crr,20);
	show(crr,20);
	return 0;
}
3.随机生成100个[10,100]之间的元素 并输出
	求生成重复次数最多的那个元素 并判断有没有一样多的情况
#include<stdio.h>
#include<stdio.h>
#include<time.h>

int main(){
	srand(time(NULL));
	//用下标标识法
	int i;
	int arr[100] = {0};
	for(i=0;i<100;i++){
		arr[i] = rand()%91+10;//10~100区间
	}
	for(i=0;i<100;i++){
		printf("%d ",arr[i]);
	}
	printf("\n");
	int brr[101]={0};//brr[num]来标识num这个数字出现的次数
	for(i=0;i<100;i++){
		brr[arr[i]]++;
	}
	//重复次数最多的那个元素,就是brr中数值最大的
	int maxi = 0;
	int same = 0;//假设没有一样的
	for(i=0;i<101;i++){
		if(brr[i]>brr[maxi]){
		maxi = i;
		same =0;//第一次出现最多的情况,暂时还没有
		}else if(brr[i] == brr[maxi]){
			same =1;
		}
	}
	printf("重复次数最多的是%d,一共出现%d次\n",maxi,brr[maxi]);
	if(same){
		printf("出现重复\n");
	}else{
		printf("没有出现重复\n");
	}
	return 0;

///因为范围是10~100
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

void chick(int *arr,int len,int *brr){
	int i;
	for(i=0;i<len;i++){
		brr[arr[i]-10]++;
	}
}

void mymax(int *brr,int len){
	int i;
	int maxi=0;
	int same=0;
	for(i=0;i<len;i++){
		if(brr[maxi]<brr[i]){
			maxi=i;
			same=0;
		}else if(brr[maxi]==brr[i]){
			same=1;
		}
	}
	printf("%d %d",maxi+10,brr[maxi]);
	printf("\n");
	if(same){
		printf("有");
	}else{
		printf("无");
	}
	printf("\n");

}
int main(){
	int i;
	srand(time(NULL));
	int arr[100];
	int brr[91]={0};
	for(i=0;i<91;i++){
		arr[i]=rand()%91+10;
	}
	chick(arr,100,brr);
	for(i=0;i<91;i++){
		printf("%d ",brr[i]);
	}
	printf("\n");
	mymax(brr,91);
	return 0;
}
4. 输入一个整数,把该整数的二进制(补码) 存储到数组中 并输出
#include<stdio.h>
#include<math.h>

void bin(int num,int arr[]){
	int i;
	for(i=0;i<32;i++){
		arr[i]=(num>>(31-i))&1;//因为计算机中保存的就是补码,所以把计算机中保存的32为补码从头开始和1&,即保存至数组中就是答案
	}	
}

int main(){
	printf("请输入一个数字:");
	int num;
	scanf("%d",&num);
	int arr[32]={0};
	bin(num,arr);
	int i;
	for(i=0;i<32;i++){
		printf("%d",arr[i]);
	}
	printf("\n");
	return 0;
}

5. 不用%x格式占位符,输出一个整数的十六进制
#include<stdio.h>

//十六进制,4个二进制位对应一个16
void hex(int num,char brr[]){
	int i;
	for(i=0;i<8;i++){
		int n = (num>>4*i) & 0xf;//n[0,15],0xf只保留了最低的四个二进制位,0000 0000 0000 0000 0000 0000 0000 0000,因为16进制4个字节字节一位,所以判断完最后的4位后,向右移动4位判断下一组
		if(n<10){//因为16进制要考虑是1~10,'A'~'F'
			brr[7-i] = n+'0';//48'0',49'1',7-i是因为最先计算出的是最后输出的
		}else{
			brr[7-i]=n-10+'A';//14-10+'A'='E'		
		}
	}
}
int main(){
	char brr[8] = {0};//因为有ABC所以用char类型
	int num;
	scanf("%d",&num);
	hex(num,brr);
	printf("0x:");
	int i;
	for(i=0;i<8;i++){
		printf("%c",brr[i]);
	}
	printf("\n");
	return 0;
}
6.先输入数列长度n,然后再输入n个整数,求n个数中的最大子串和
  7 :   1   3  -2  7  -8  6  -2    最大和子串为  1+3-2+7=9
  6 :  -1   3  -2  4  -5  4                     3-2+4 = 5
  4 :  -1  -2  -3 -4                              -1 = -1
#include<stdio.h>

int max(int arr[],int len){
	int max = arr[0];//记录最大值不能是0,因为有可能最大子串和是负数
	int sign = 0;//用来一直加
	int i;
	for(i=0;i<len;i++){
		if(sign>0){
			sign += arr[i];
		}else{
			sign = arr[i];
		}
		if(sign>max){
			max = sign;
		}
		//或者
		//sign += arr[i];
		//if(sign>max){
			//max = sign;//max永远保留历史相加最大值
		//}
		//if(sign<0){
		//	sign=0;//前面加起来为负数,这直接置0重新加
		//}
	}
	return max;
}

int main(){
	int n;
	printf("数字长度为:");
	scanf("%d",&n);
	int arr[n];
	int i;
	for(i=0;i<n;i++){
		scanf("%d",&arr[i]);	
	}
	printf("%d:",n);
	for(i=0;i<n;i++){
		printf("%d ",arr[i]);
	}
	printf("\n");
	int m = max(arr,n);
	printf("最大子串和是:%d\n",m);
	return 0;
}
7.输入第一个数组长度
	并依次输入这个数组的元素
  输入第二个数组长度
	并依次输入这个数组的元素
  (1)输出在两个数组中都存在中的元素
  (2)输出在第一个数组但不在第二数组中的元素
  (3)合并两个数组 并 去除重复的元素 输出
#include<stdio.h>

int same(int arr[],int len1,int brr[],int len2,int crr[]){
	int i,j,k=0;
	for(i=0;i<len1;i++){
		for(j=0;j<len2;j++){
			if(arr[i]==brr[j]){
				crr[k++]=arr[i];
				break;
			}
		}
	}
	return k;
}
int  xor(int arr[],int len1,int brr[],int len2,int crr[]){
	int i,j,k=0;
	for(i=0;i<len1;i++){
		int have =0;
		for(j=0;j<len2;j++){
			if(arr[i]== brr[j]){//第一组和第二组的元素全部比较后,确定没有则不执行这个if,即have还是0,有一个相同则have=1,并不再继续看第二组后面的数,开始第一组的下一个元素判断
				have = 1;
				break;
			}	
		}
		if(!have){
			crr[k++]=arr[i];
		}
	}
	return k;
}

void readarr(int arr[],int len){
	int i;
	for(i=0;i<len;i++){
		scanf("%d",&arr[i]);
	}
}
void showarr(int arr[],int len){
	int i;
	for(i=0;i<len;i++){
		printf("%d ",arr[i]);
	}
	printf("\n");
}
int main(){
	printf("请输入第一个数组的长度:");
	int len1;
	scanf("%d",&len1);
	int arr[len1];
	readarr(arr,len1);
	printf("请输入第二个数组的长度:");
	int len2;
	scanf("%d",&len2);
	int brr[len2];
	readarr(brr,len2);
	int crr[len1+len2];
	int ret = same(arr,len1,brr,len2,crr);
	printf("两组相同的:");
	showarr(crr,ret);
	ret = xor(arr,len1,brr,len2,crr);
	printf("第一组有第二组没有的:");
	showarr(crr,ret);
	int res = xor(brr,len2,arr,len1,crr+ret);
	printf("两组集合,除去相同的:");
	showarr(crr,ret+res);
	return 0;
}
8.八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法,并显示每一种摆法
#include <stdio.h>

int attack(int queens[],int row,int col){
	int i;
	for(i=0;i<row;i++){//row和col都是下标 和对应的第几行第几列少了1
		if(col == queens[i]){//在col该列上之前有一个皇后 
			return 1;	
		}
		if(row-i == col-queens[i] || row-i == queens[i]-col){//在对角线上有皇后
			return 1;
		}
	}
	return 0;
}
void show(int queens[],int num){
	int i;
	for(i=0;i<num;i++){
		printf("%d ",queens[i]+1);	
	}
	printf("\n");
}
//要摆放num个皇后
int queen(int num){
	int res = 0;//用于记录摆放方法的种数 num表示总共有多少个皇后需要摆放
	//记录皇后摆放的位置只需要一维数组
	int queens[num];//用于保存8个皇后的位置  行和列  每一行只能摆放一个皇后
	int i;
	for(i=0;8<num;i++){//init
		queens[i] = 0;	
	}
	int row = 0;//目前成功摆放了几个皇后
	int col = 0;//每一行 都是从第一列是试探
	//不断去摆放 直到成功   成功之后探索下一种方法 什么时候探索结束
	while(1){
		//相当于在第row+1行的col+1列摆放一个皇后 
		if(!attack(queens,row,col)){//在row+1行,col+1列摆放皇后并不会和之前的冲	
			queens[row] = col;//在这一行摆放一个皇后
			row++;//下一行
			col = -1;//下一行从第1列开始尝试摆放
			if(row == num){//所有的皇后都已摆放完成
				show(queens,num);
				res++;//是一种摆法
				//重新去最后一行尝试  得从当前列的下一列开始
				col = queens[row-1];
				row--;
			}//这里是在最后一行进行多次尝试
		}
		col++;//这一列不能摆放 继续尝试下一列
		while(col>=num){//表示最后一行的列判断已经到了最后一个位置,这时候就要用回溯法
			col = queens[row-1]+1;
			--row;
			if(row<0){//连第一行都无法摆放
				return res;	
			}
		}
	}
}


int main(){
	//保存皇后的位置  int board[8][8] = {}; 不需要
	//queens[0] 是第一行皇后摆放的列位置
	//queens[5] 是第六行皇后摆放的列位置

	int res = queen(8);
	printf("一共有%d种摆放方法!\n",res);

	return 0;	
}

9.模拟斗地主
	洗牌之后 ,显示每个玩的17张牌(需要显示JQKA 花色 或者 大王  小王)
	最后显示 三张底牌
	如:
	红A  黑A    花K   方J   红10   黑7  ....
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void cash(int card[],int num){
	int i;
	for(i=0;i<num;i++){
		int k = rand()%num;	
		int tmp = card[i];
		card[i] = card[k];
		card[k] = tmp;
	}
}

void show(int card[],int num){
	int i;
	for(i=0;i<num;i++){
		if(card[i] == 52){
			printf("小王 ");	
		}else if(card[i] == 53){
			printf("大王 ");	
		}else{
			switch(card[i]%4){
				case 0:printf("黑");break;
				case 1:printf("红");break;
				case 2:printf("梅");break;
				case 3:printf("方");break;
			}
			switch(card[i]/4){
				case 0://A
					printf("A ");break;
				case 10://J
					printf("J ");break;
				case 11://Q
					printf("Q ");break;
				case 12://K
					printf("K ");break;
				default:
					printf("%d ",card[i]/4+1);break;
			}
		}
	}
	printf("\n");
}

void deal(int card[],int num,int palyer[3][17],int di[]){
	int i;
	for(i=0;i<num-3;i++){
		palyer[i%3][i/3] = card[i];	
	}
	di[0] = card[51];
	di[1] = card[52];
	di[2] = card[53];
}


int main(){
	//表示一副扑克牌
	//表示 A  2  J  Q  K  大小王  数值
	//0-53  0 1 2 3  'A'  4 5 6 7 '2'  8 9 10 11 '3'
	srand(time(NULL));
	int card[54] = {0};//一副扑克牌54张  A-10 JQK  13*4=52+2=54 
	int i=0;
	//初始化一副新牌
	for(i=0;i<54;i++){
		card[i] = i;	
	}
	//52 53  小王 大王
	//card[i]  card[i]/4 == 1 A 2 2  10  11 J 12 Q 13 K 
	//黑 红 梅 方  card[i]%4  0 1 2 3
	
	//显示一下
	show(card,54);
	//洗牌
	cash(card,54);	
	show(card,54);
	
	int palyer[3][17] = {};
	int di[3] = {};

	deal(card,54,palyer,di);
	for(i=0;i<3;i++){
		printf("玩家%d:",i+1);
		show(palyer[i],17);
	}
	printf("底牌:");
	show(di,3);

	return 0;	
}

10.卡拉兹:
#include <stdio.h>


//unsigned int  === size_t
size_t callatz(size_t num){
	if(num == 0){
		return 0;	
	}
	size_t cnt = 0;
	while(num != 1){
		if(num&1 == 1){
			num = (3*num + 1)/2;
		}else{
			num  = num/2;	
		}
		cnt++;
	}
	return cnt;
}

int main(){
	size_t num = 0;
	printf("请输入一个正整数:");
	scanf("%u",&num);
	printf("%u \n",callatz(num));
	
	return 0;	
}
11.本题要求实现一个对数组进行循环右移操作
如输入:6
	 数组元素为: 1 2 3 4 5 6
	 循环右移位数:2
  输出:5 6 1 2 3 4
#include <stdio.h>

void move(int arr[],size_t len,size_t bit){
	bit = bit%len;//10%8=2,这是实际要移动的长度=移动位数%数组长度
	int brr[bit];
	int i;
	for(i=0;i<bit;i++){
		brr[bit-1-i] = arr[len-1-i];//右移10位相当于右移2位,所以把最后两位保存下来
	}
	for(i=0;i<len-bit;i++){//范围是数组长度-实际要移动的长度
		arr[len-1-i] = arr[len-1-bit-i];//把除了上面保存到brr中的元素都往后复制
	}
	for(i=0;i<bit;i++){
		arr[i] = brr[i];//把brr中的元素存入arr空缺位置中
	}
}

int main(){
	int arr[] = {1,2,3,4,5,6,7,8};
	size_t len = sizeof(arr)/sizeof(arr[0]);
	move(arr,len,10);
	int i;
	for(i=0;i<len;i++){
		printf("%d ",arr[i]);	
	}
	printf("\n");
	return 0;	
}

指针:c语言灵魂

普通的变量传递到函数中,对其进行赋值操作并不会影响原来实参的值
数组作为函数传递到函数中,如果对数组中的内容进行修改会影响到实参数组元素的值

c语言中参数的传递其实是值复制传递

在函数调用时,实参把值赋值给形参,修改形参并不会影响实参的值

变量的地址:内存地址 (变量存储在内存中的位置 编号)
可以用%p显示一个变量的地址 返回十六进制的数字
任意类型变量取地址运算符& 内存地址

	int a=10
	double d=3.14
	char c= ‘a’
	//取址运算符  内存地址
	printf(“%p”,&a)
	printf(“%p”,&b)
	printf(“%p”,&c)//默认返回十六进制
	scanf(“%p”,&a)//从控制台读取数据时 对变量取址
	printf(“%p”,&10)//这样是不行的,&取址运算符的操作数必须是左值,就是变量名
	int x = &a;这样会出警告  本质上是int,但是其实不是int

内存地址是一个十六进制的数值,可以用变量来保存变量的地址,即函数中return p,p是地址,在主函数中,可以用int dest=p来接收地址

内存地址即指针

定义指针变量来保存内存地址

一个程序(进程)有4G的虚拟内存,4G用数值表示[0,0xffffffff]
4G的内存编号是从0开始,到0xffffffff=4*1024MB=4 * 210 * 210kb=4 * 220 * 210 Bit=4 * 230 byte=232字节(byte)一个字节一个内存编号[0,2^32-1]
1024=210

指针变量

即保存内存地址的变量
一块内存用于保存什么数据,决定了该内存的大小
char 1byte
…
char a = ‘a’;
int b = 3;//4字节
char *pa = &a;
int *pb = &b;
pa,pb都是指针变量,用于存储指针(内存变量)对普通变量取&
//定义指针变量:数据类型 *指针变量名;
void func(int a){
	printf(%p,&a)
}
int main(){
	int a=10
	printf(%p,&a)
	func(a)
}//输出的答案是不一样的
虽然值都是10,但是变量在不同函数中,所以位置不同,

数据类型 * 这一个整体称为指针变量的类型

int * p1,p2;//这个p1的类型是int* ,p2的类型是int,若是要把两个都定为指针变量,必须都加* ,
这种情况是 p1指针,p2整型

所以 int * p1.*p2这是定义两个指针
*和旁边两个之间有没有空格都行

指针变量的初始化

int a = 0;//一般来说,会定义变量时对其初始化”零”
int *p = null;
当一个指针定义之后,如果不确定存储什么数据,一定要初始化为null
空指针 null 悬空指针 本质上是编号为0的地址
int a=10
int *p=&a;//有确切的值的时候的初始化

int a=10,b=20;
printf(%p%p,&a,&b0)
printf(%d%d,*&a,&*b)//这种就是取地址所指向的值,*和&是相互抵消的

int  *p=&a//这个*是指针类型的一部分,不是取值运算符的作用,定义的时候类型名和*是一个整体,都是指针定义的部分
printf(%p,p);//取a地址
print(&d,*p)//这个就是取a的值,因为*p=*&a
p=&b;//修改指针变量的值
printf(%p,p)
printf(“%d”,*p)//这个就是取b的值

取值运算符

*取内存地址中存储数据的数值
*操作数  操作数必须是指针运算
*&a == a;  //&a是取地址,*(&a)取地址中的数值


void func(int *p)//指针变量用于存储内存地址
	printf(%p,p)//地址
	func函数中 得到了main:a的内存地址
	*p=1111;//修改内存中的数值  *(&a(从main函数中来的))  main:a=1111
int main(){
	int a=10
	printf(%p,&a)
	func(&a);//传a的地址,因为形参是指针变量
	printf("%d",a);//查看a的值是否改变
}
写一个函数交换两个变量的值
//下面一个例子是错误示例,只是地址交换
int a=10,b=20
swap2(&a,&b)//这个也达不到交换的目的
void swap(int *pa,int *pb){//!这个*只是指针类型的必要要素,不是取值运算符的判断!!
	int *pt = pa;  //将pa即&a即a的地址赋给pt这个指针变量   
	pa=pb;//b的地址给pa,即将a的地址改为b的地址
	pb=pt;
} //始终停留在交换地址层面
//这个例子是正确的
void swap(int *pa,int *pb){
 int tmp=*pa;   //*(&a) 即a的值放到tmp中过渡
*pa=*pb  //*(&b)即b的值放到*(&a)即a的值中
*pb=tmp;//你要交换值,就要到值这个层面去
}

野指针:

我们无法确定一个指针是否是野指针,因为随机给的垃圾值可能是正确的,也可能是错误的

void swap4(int *pa,int *pb){
	int *pt;//定义了一个指针变量pt,pt没有初始化,所以里面是一个垃圾值
	//这个垃圾值就被当做内存地址,后面值就赋在这个垃圾地址上,有可能该地址不能使用,也有可能访问没有权限   这种称为野指针,非常危险,
	*pt=*pa//因为一级指针*pa是=a,是值不是地址,后面会接触二级指针,二级指针是*ppa=*&p=p=&a是地址,不是指值,是指地址
	*pa=*pb
	*pb=*pt
}//会出现 段错误(核心已转储)
所以建议指针初始化为null
	在判断一个指针是否可以进行*运算时
	if(p!=NULL){
		*p;//意味着可以运算,就能排除野指针
	}//后面一般用一个头文件
	#include<assert.h>
	assert(p!=NULL));

数组名 即内存地址

数组是一片连续的内存,数组名就是这片内存的首地址

int arr[5]={1,2,3,4,5};
printf(%p,arr);//会打印数组内存的首地址=首元素的地址
printf(%p,&arr[0])//首元素的地址,arr[0]是首元素,&arr[0]是首元素地址
printf(%p,&arr)也和上面一样

func(arr,5)//所以数组传递就是传了地址过去,所以在函数中改变值能影响到main中

void func(int *arr,int len){
	arr[0]=119;
	printf(%d,arr[0]);
	printf(%d,0[arr])//两个都行
}
int mian(){
	int arr[5]={1111,9527,1314,520,8888};
	func(arr,5);//传数组时一般带数组长度,
	int i;
	for(i=0;i<5;i++)
		printf(%d,arr[i]);
		printf(%d,i[arr]);
	return 0;
}

[ ]运算符:

arr[i]  <====>  *(arr+i)  <====>  i[arr]
数组名[下标]=[下标]数组名
为啥呢,*(arr+i)=arr[i]    *(i+arr)=i[arr] ;// 因为仅arr时,就是数组名,返回的是首	元素的地址,*(arr+i) 首先arr是首地址地址+i就是首元素的后面第i个元素的地址,最后									加上个*,  地址符号&和* 相互抵消,最终达到arr。
同理*(p+i)=p[i]  *(i+p)=i[p];//func(int *p,int len)//传递数组到函数中
&arr[0] 首元素地址 <===>   &(arr[0])  <===> &(*(arr+0))  <===>  &(*arr)  <==> arr
也都是一样的

printf(%p,arr)是个地址
int *p=arr//可以保存,arr类型为 int
printf(%p,p)
printf(%d,*p)

int *p = null;
p=arr;//两个都是存了地址
for(i=0;i<5;i++){
	printf(%d,p[i])
}
	
&arr 值和arr,&arr[0]相等,但是类型不同
&arr// 是一个数组的地址
p = &arr;   // p是一个整数类型的地址

指针大小

我们的系统的sizeof(指针)是恒等于4的,但是不同操作系统可能为8
内存是个数值,上面说过,在我们的系统里意味着只需要4个字节就可以保存任意一个内存
地址,指针变量的字节大小恒为4,

linux i386 cpu 32位 恒为4
linux x64 cpu 64位 sizeof(指针)    8

printf(%u,sizeof(char*))
printf(%u,sizeof(int*))
printf(%u,sizeof(doule*))
//答案都是4,%u是无符号整数

char arr[5]={'a','b','c','d','e'}
int *p =NULL;
p= arr;
printf(%u,sizeof(arr))求数组所占内存大小  5*4=20
printf(%u,sizeof(p))  p是一个指针变量4

void func(int arr[5]){
	printf(%u,sizeof(arr))
}//函数中为4,Int arr[5] 和 int arr[] 和 int *arr 没有区别,都表示数组元素首地址(在形参中)

Void bar(int *arr){
	Printf(%u,sizeof(arr))
}//4   

为啥要实参传形参时同时传递数组的长度

因为数组名作为实参传递时,退化为首元素地址(指针)
所以在形参表中,int arr[10] == int arr[ ] === int *arr
所以传递时一定要传数组的长度,因为在函数中你求不出数组的长度,要人为传递
在函数中Sizeof(arr)/sizeof(arr[0])=1   因为两个都是指针的长度,求不出数组的长度

如果没有传参的要求,可以不使用指针,但是要求函数中修改参数,就必须要用指针

Int arr[5] ={119,120,9527,1314,520}
&arr+1  //加整个数组的长度4*5=20个字节,数组加1加整个数组

Int * p=arr
for(i=0;i<5;i++){
	printf(“%p+%d=%p”,p,i,p+i)
}//指针地址+1加4字节

Double+8byte
Char+1byte

指针+1:指针偏移一个单位内存大小
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值