#include<stdio.h>
#include<stdlib.h>
//一级指针主要用途 :
//1.函数改变外部变量
//2.跨进程改变变量
//3.数组作为参数,(数组会退化成一个参数),指针可以作为形参接收数组首地址
void main1()
{
int num = 10;
num = 5;//直接修改
printf("%d\n",num);
int *p = #
*p = 3;//间接修改
printf("%d\n",num);
getchar();
}
void ChangeNum(int num)
{//函数形参有副本机制,接收一个值,新建一个变量,开辟一个地址接收这个值
//要在函数里改变变量要用指针
num = 3;
printf("changenum=%p\n",&num);
}
void main2()
{
int num = 10;
printf("main=%p\n",&num);
ChangeNum(num);//传递数据
printf("num=%d",num);//结果还是10,没有改变
getchar();
}
void ChangePnum(int *p)
{
*p = 2;// * 就是根据地址与类型取出数据内容,函数改变外部
// 变量必须用指针
}
void main3()
{
int num = 10;
//int *px = #
//ChangePnum(px);
//printf("%d\n", *px);
ChangePnum(&num);// 传递指针
printf("%d",num);
getchar();
}
void test(int a[10])//数组是个例外,拒绝副本机制,数组当做形参的时候是地址
{
printf("test a有%d字节\n",sizeof(a));//结果是4个字节
int b[10] = { 1,2,3,4,5,6,7,8,9,0 };//结果是40个字节,不作为形参就是一个真正的数组
printf("test b有%d个字节\n",sizeof(b));
}
void test1(int a[10])
{
a[0] = 25;//数组作为参数,改变数组,等同于直接操作外部数组
for (int i = 0; i < 10; i++)
{
printf("test1=a[%d]=%d\n",i,a[i]);
}
}
void test2(int *p)
{
*p = 33;
for (int *px = p; px < p + 10; px++)
{
printf("%p,%d\n",px,*px);//打印地址和数据
}
}
void main4()
{
int a[10] = { 1,2,3,4,5,6,7,8,9,0 };
//打印数组大小和元素个数
printf("main a有 %d字节,有%d元素\n",sizeof(a),sizeof(a)/sizeof(int));
test(a);
test1(a);//函数test1内的改变,直接影响main里的数组
for (int i = 0; i < 10; i++)
{
printf("main=a[%d]=%d\n",i,a[i]);
}
test2(a);//根据地址改变数据
getchar();
}
void main()
{
int a[10] = { 1,2,3,4,5,6,7,8,9,0 };
printf("%p",a);//数组地址是数组第一个元素的地址,线性排列,因为是int类型,地址之间隔4隔字节
getchar();
}
第二部分
#include<stdio.h>
#include<stdlib.h>
//一级指针的用途:可以储存一个数组的首地址,可以用指针的方式和下标的方式访问
//指针循环需要一个一级指针
void main6()
{
int a[10] = { 1,2,3,4,5,6,7,8,9,0 };
printf("%p\n",a);//a是一个常量指针
int *p = a;//这里的a 也是int*类型
printf("\np=%d,a=%d\n",sizeof(p),sizeof(a));//p=4个字节,a=40个字节,a本身也是4个字节,但是编译器做了特殊处理
//数组名编译器做了特殊处理
for (int i = 0; i < 10; i++)
{
//printf("\n%d,%p", a[i], &a[i]);
printf("\n%d,%p\n", p[i],&p[i]);//和上面是一样的
}
for (int i = 0; i < 10; i++)//下标循环
{
printf("\n%d,%p,%d,%p",p[i],&p[i],*(p+i),p+i);//前两个和后两个结果一样
} //如果p的地址是300500,p+1的地址就是300504,因为是int类型,所以4个字节
//p[i]=*(p+i) &p[i]=p+i
printf("\n");
//指针循环,从最后一个到第一个
for (int *px = a + 9; px >= a; px--)
{
printf("\n%d,%p",*px,px);
}
getchar();
}
int go()//return也有副本机制,是放在寄存器里的,不能取地址
{
int a = 3;//auto自动变量
printf("%p\n",&a);
return a;
}
void main7()
{
printf("%d\n",go());
//printf("%p",&go());//函数的返回值不能取地址
getchar();
}
//一级指针作为函数的返回地址,一定不能返回指向栈的地址
int *go1()
{
//static int a = 3;//加上static就不会指向栈了
//调用函数后值就不会发生变化了
int a = 3;
printf("%p\n",&a);
return &a;
}
void main8()
{
int *p = go1();
//printf("\n\n\n\n");//函数执行完之后内存被回收,不使用还是原来的值,
//使用了就会发生变化(这里并没有发生这种情况)
printf("%d,%p",*p,p);
getchar();
}
void main9()
{
//指针储存常量字符串首地址
char *p = "tasklist & pause";
//*p = 'a';//报错,常量字符串不可以修改
//printf("%p\n",p);//p的地址对应的就是tasklist & pause
char *px = p;
while (*px != '\0')//输出tasklist & pause
{
putchar(*px);
px++;//指针向前移
}
//system(p);//执行tasklist和pause
getchar();
}
void mainA()
{
int num = 10;
//double *p = #
int *p = #//指针的类型,类型决定了步长
//printf("%f", *p);//垃圾数据,类型不对
printf("%d",*p);
getchar();
}
void mainB()
{
int num = -1;
unsigned int *p1 = #//指针类型决定如何解析
int *p2 = #
printf("%u,%d",*p1,*p2);//%u是4294967295 %d是-1
getchar();
}
第三部分
#include<stdio.h>
#include<stdlib.h>
//一级指针的用途:简介访问结构体,创建一个堆上个变量,储存这个变量的地址
//创建堆上的动态数组或者单独一个元素
//访问结构体,共用体,枚举体
struct info
{
int num;
float score;
};
void main1()
{
//如何构建一个指针变量访问结构体info
struct info info1;//构建一个变量info1
//赋值表达式的值等于被赋值变量的值
printf("%d,%f\n", info1.num = 10, info1.score = 29);
struct info *p1 = &info1;
//指针访问结构体的两种方式
printf("%d,%f\n", (*p1).num, (*p1).score);//简写为下面
printf("%d,%f\n", p1->num, p1->score);//和上面结果一样
//malloc的返回值是空指针,所以要类型转换,分配内存之后等价于他初始化了
struct info *p2 = (struct info*)malloc(sizeof(struct info));
p2->num = 20;
p2->score = 19.8;
printf("%d,%f\n", (*p2).num, (*p2).score);
printf("%d,%f\n", p2->num, p2->score);
getchar();
}
void main2()
{
struct info *p2 = (struct info*)malloc(sizeof(struct info)*5);//构建动态数组
int i = 0;
for (struct info *px = p2; px < p2 + 5; px++)//指针循环
{
px->num = i;
px->score = i + 3.5;
i++;
printf("\n%d,%f", px->num, px->score);
}
for (int j = 0; j < 5; j++)//下标访问
{
p2[j].num = i;
p2[j].score = i + 3.5;
i++;
printf("\n%d,%f", p2[j].num, p2[j].score);
}
getchar();
}
enum MyEnum
{
//在没有被赋值(小兵=5之类)的情况下,枚举值是按照0,1,2……排列的
小兵,班长,排长,连长,师长,军长,司令
};
void main3()
{
enum MyEnum myenum1 = 司令;
printf("%d\n", myenum1);//6
enum MyEunm *p = &myenum1;//创建一个指针访问枚举体
printf("%d\n", *p);//6
getchar();
}
#define p(x) x*x//自己实现函数,原理就是替换
#define px(x) (x)*(x)
#define getname(x) #x//#x的作用是自动加上""
void main()
{
//传递函数名main,打印出"main"
printf("%p\n", main);//只是main的地址,没办法获取名称
printf("%d\n", p(3));//9
printf("%d\n", p(1+3));//1+3*1+3=7
printf("%d\n", px(1 + 3));//(1+3)*(1+3)=16
printf("%s\n", getname(main));
getchar();
}
16万+

被折叠的 条评论
为什么被折叠?



