写了没用上(本来给新生写的),算了,丢博客吧,就当纪念一下,顺便可以复习(虽然说可能用不上罢了)
如果有什么错滴滴我(虽然说可能也没多少人看罢了)
// 指针的简单应用
/*
参考链接https://www.runoob.com/cprogramming/c-pointers.html
上述链接里面讲的已经很详细了,建议去看QAQ
*/
/*
废话:
因为部分人可能之后也不会用c艹什么的,所以这都是c语言写的(毕竟考试考的是c么)
指针刚开始学起来发现挺痛苦的,但是,到后面你就会发现大一下学期数据结构还是要学滴
这代码我一个人写的,可能会有些地方有错误或者写的不详细,见谅QAQ
*/
#include <stdio.h>
#include <stdlib.h>
void test1() // 指针基本用法
{
int a = 10;
printf("a的地址为%p\n", &a); // 输出a的地址 %p 以16进制的形式输出内存地址
printf("a的值为%d\n\n", *&a); // 输出a的值(可知*&a等于a,即*和&可以抵消) %d 输出有符号十进制整数
/*
我们可以看到平常我们用的printf中'&'实际上是取地址的意思~~
而'*'用来来返回位于操作数所指定地址的变量的值
*/
int *ip; // 定义一个int类型指针,不过指针最好要进行赋值,没经过赋值的指针叫做“野指针”(即不知道指向哪里)
ip = &a; // 将a的地址赋值给指针
// 上述也可以转换为: int *ip=&a;
/*
同时指针没有确切的赋值可以用NULL 如ip=NULL
赋为 NULL 值的指针被称为空指针。NULL 指针是一个定义在标准库中的值为零的常量。
NULL的地址为0x0
*/
printf("ip的值为%p\n", ip);
printf("ip指向的地址的值为%d\n\n", *ip);
/*
我们可以发现ip的值为a的地址,ip指向的地址的值为a的值(废话QAQ)
*/
}
void test2() // 指针大小
{
int *_int_;
char *_char_;
double *_double_;
float *_float_;
short *_short_;
printf("int指针的大小为:%d\n", sizeof(_int_)); // sizeof函数用处:返回一个变量或者类型的大小(以字节为单位)
printf("char指针的大小为:%d\n", sizeof(_char_));
printf("double指针的大小为:%d\n", sizeof(_double_));
printf("float指针的大小为:%d\n", sizeof(_float_));
printf("short指针的大小为:%d\n\n", sizeof(_short_));
/*
我们可以发现上述指针大小都是一样的(32位系统和64位系统跑的可能不一样)
why?
毕竟指针是来存地址的(也就是%p输出的那大串),不同类型的指针只是指向的类型不一样罢了
*/
}
void test3() // 指针的算术运算
{
int x;
int *_ip_ = &x;
printf("_ip_的地址为:%p\n", _ip_);
printf("_ip_ +1的地址为:%p\n\n", _ip_ + 1);
/*
我们可以看到指针地址的算术运算并不是地址加1,而是地址加上一个4
*/
// 指针的算术运算和其他的差不多所以不码了(欸,就是偷懒~~)
}
void test4() // 杂,基本用不到
{
/*
int num = 0x10203040;
int *p1 = #
short *p2=#//这里可能会报warning,但只是警告而已,并不代表错误
printf("int类型 *p1=%p\n",*p1);//10203040
printf("short类型 *p2=%p\n",*p2);//3040
printf("short类型 *(p2+1)=%p\n",*(p2+1));//1020
*/
/*
num在linux/window系统里是倒着存数据的
即你赋值0x10203040,但是存的数据可能是0x40302010
*/
}
void test5() // 指针套指针
{
int num = 10;
int *p1 = #
int **p2 = &p1;
printf("p1=%p\n", p1);
printf("*p1=%d\n", *p1);
printf("*p2=%p\n", p2);
printf("**p2=%d\n", **p2);
// 没啥说的,只是'*'和'&'的反复纵跳而已
}
void test6() // 指针与数组的简单应用
{
int num[] = {1, 2, 3};
int *p = num;
p[1] = 22; // 可以直接用下标来对数组进行赋值
printf("num[1]=%d", num[1]);
}
void test7() // 指针常量与常量指针
{
int a = 10, b = 5;
int *const p1 = &a; // 指针常量
*p1 = 0; // 成功
// p1=&b;//失败
/*
即指针常量不能改地址
*/
const int *p2 = &a; // 常量指针
//*p2=0;//失败
p2 = &b; // 成功
/*
即常量指针不能改数的值
*/
}
void test8() // 指针数组与数组指针
{
int a = 1, b = 2, c = 3;
int num[3] = {a, b, c};
int *p1[3]; // 指针数组 即3个int型的指针
int(*p2)[3]; // 数组指针 即1个数组类型的指针
// 用法
p1[1] = &a;
p2 = #
}
void test9_1(int x, int y) // 错误示范
{
int temp = x;
x = y;
y = temp;
}
void test9_2(int *x, int *y) // 正确示范
{
int temp = *x;
*x = *y;
*y = temp;
}
void test9() // 指针交换两个数的值
{
int a = 10, b = 5;
printf("a=%d,b=%d\n", a, b);
test9_1(a, b); // 值传递,不能改变这里ab的值,即这函数拷贝对应的值过去了
printf("a=%d,b=%d\n", a, b);
test9_2(&a, &b); // 地址传递,能改变这里ab的值,根据传递过去的地址用*找到地址对应的值,并且进行了修改
printf("a=%d,b=%d\n", a, b);
}
int *test10_1(int x) //错误示范
{
int a=10;
int *p = &a;
return p;
//这只是个示范,即告诉你指针函数是函数返回一个指针,但是实际上最好别这么做(返回函数里面的变量)!!!详细看以下
}
int *test10_2(int x) //这种返回一个指针的才是指针函数
{
int *p = (int *)malloc(sizeof(int));//malloc为stdlib.h中的一个函数,用来分配内存
*p=x;
return p;
}
void test10() // 指针函数(test10不是指针函数)
{
int a = 10;
int *ip = test10_1(a);//错误示范
printf("test1---*ip=%d\n", *ip);//正常输出10
printf("test1---*ip=%d\n", *ip);//错误输出
/*
原因:发生了 悬挂/悬空 指针错误,因为函数返回的地址是一个临时的变量的地址(这里是x),
当函数结束的时候,这个空间也就会释放,值也就可能不是原本的值了
至于第一次正常输出好像是因为有保护机制(再问下去我这个蒟蒻也不知道啊~~~QAQ)
解决办法:返回static修饰的变量/全局变量的地址,用malloc动态内存分配,等等……
(反正就是一般别返回函数里面定义的变量啦,会被回收机制释放的(毕竟要保证所指向的地址对应的值不会被垃圾回收就行啦))
*/
ip = test10_2(a);//正确示范
printf("test2---*ip=%d\n", *ip);
printf("test2---*ip=%d\n", *ip);
}
int test11_add(int x, int y)
{
return x + y;
}
int test11_sub(int x, int y)
{
return x - y;
}
void test11() // 函数指针
{
int a = 10, b = 5;
int (*fun)(int x, int y); // 函数指针(指向函数的指针)
// 简单用法:
fun = test11_add;
printf("test11_add(a,b)=%d\n", fun(a, b));
fun = test11_sub;
printf("test11_sub(a,b)=%d\n", fun(a, b));
}
struct test12_age
{
int year, month, day;
};
void test12() // 指向结构体变量的指针
{
struct test12_age a = {1, 2, 3}; // 定义结构体变量并且赋值
struct test12_age *p = &a;
printf("year=%d,month=%d,day=%d\n", a.year, a.month, a.day); // 结构体变量.成员名
printf("year=%d,month=%d,day=%d\n", p->year, p->month, p->day); // 用法1 指针变量->成员名
printf("year=%d,month=%d,day=%d\n", (*p).year, (*p).month, (*p).day); // 用法2 (*指针变量).成员名
}
int main()
{
// test1();//指针基本用法
// test2();//指针大小
// test3();//指针算术运算
// test4();//杂,数据存放(逆序存放)
// test5();//指针套指针
// test6();//指针与数组的简单应用
// test7();//指针常量与常量指针
// test8();//指针数组与数组指针
// test9();//指针交换两个数的值
// test10();//指针函数
// test11();//函数指针
// test12();//指向结构体变量的指针
// end 不码了,开摆!~
return 0;
}