lsfreeing 2019-12-28
函数的值传递,无法通过调用函数,来修改函数的实参。
指针是什么
指针本质是一个地址值:
#include <stdio.h> int main(void){ int age; //定义了一个指针 //指针是一个变量 //这个变量的名称是 p //这个指针,可以用来指向一个整数! //就是说:p的值是一个整数的地址!!! int * p; //指针p指向了age //p的值,就是变量age的地址 p = &age; scanf("%d", p); printf("age=%d\n", age); return 0; }
指针的定义
int p;
或者:
int p;
或者:
int * p;
c语言中的指针,占用4个字节。
指针的初始化
demo:
#include <stdio.h> int main(void) { int mygirl = 18; int *p1 = &mygirl; int *p2 = p1; return 0; }
访问指针
demo
#include <stdio.h> int main(void) { int mygirl = 18; int *p1 = &mygirl; int *p2 = p1; //1. 访问(读、写)指针变量本身的值!!!(和其他普通变量的访问方式相同) int *p3; p3 = p1; //读指针p1的值, 设置指针p3的值 printf("p1=%d\n", p1); //不建议使用该方式 //使用16进制打印,把地址值当成一个无符号数来处理的 printf("p1=0x%p\n", p1); printf("p1=0x%x\n", p1); printf("p1=0x%X\n", p1); return 0; }
2进制与16进制(补充)
10进制,2进制,16进制
10进制:
每一位,有10种状态(0,1,2,3,4,5,6,7,8,9),逢10进1
2进制:
计算机只识别2进制
每一位,有2种状态(0,1)
16进制:
每一位,有16种状态(0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f)
为了描述方便,我们常常把一些二进制数据,转换为16进制表示
比如:
10进制:257
二进制:100000001
16进制:0x101
访问指针所指向的内容
#include <stdio.h> int main(void) { int my_girl = 18; int *p = &my_girl; int x; x = *p; //*是一个特殊的运算符,*p表示读取指针p所指向的变量的值 printf("x=%d\n", x); printf("*p = %d\n", *p); my_girl++; printf("*p = %d\n", *p); return 0; }
空指针,就是值为0的指针。
int *p;
p = 0;
#include <stdio.h> int main(void) { int *p; p = 0; //p就是一个空指针! printf("%p\n", p); //访问空指针指向的值,将导致程序崩溃!!! printf("%d\n", *p); //读取 地址为0的int类型变量 system("pause"); printf("程序结束\n"); return 0; }
3.空指针的使用
1)指针初始化为空指针
例如: int p = 0;
建议这样使用:
int p = NULL;
目的就是,避免访问非法数据。
2)指针不再使用时,可以设置为空指针
int *my_girl = &xiao_long_lv;
my_girl = NULL;
1)表示这个指针还没有具体的指向
int *p = NULL;
if (!p) {
......
}
#include <stdio.h> struct friend { char name[32]; char sex[3]; int age; }; int main(void) { struct friend f1 = { "小龙女", "女", 18 }; //定义了一个指针变量p, //这个my_girl可以指向一个struct friend类型的变量 struct friend *my_girl; my_girl = &f1; //直接通过结构体变量来访问该结构体内部的成员 printf("%s, %s, %d\n", f1.name, f1.sex, f1.age); //通过指针p来访问结构体内部的成员 //方式1, 很少使用该方式 printf("%s, %s, %d\n", (*my_girl).name, (*my_girl).sex, (*my_girl).age); //方式2 printf("%s, %s, %d\n", my_girl->name, my_girl->sex, my_girl->age); return 0; }
指针的自增运算
#include <stdio.h> int main(void) { int ages[] = {20,15,16,14,23,28,30,38, 35, 32, 26}; int len = sizeof(ages) / sizeof(ages[0]); //先使用数组的方式来访问 for (int i=0; i<len ; i++) { printf("第%d个学员的年龄是:%d\n", i+1, ages[i]); } //使用指针来访问 //int *p = ages; //指针p指向ages[0] int i = 0; for (int *p = ages; p < ages+len ; p++, i++) { printf("第%d个学员的年龄是:%d\n", i+1, *p); } return 0; }
指针的自减运算
#include <stdio.h> #include <string.h> /** * 让用户输入一个字符串,然后反向输出(不能改变原来的字符串!) * "12345" 逆转成 "54321" */ int main(void) { char line[128]; int len; char tmp; printf("请输入一个字符串: "); gets(line); len = strlen(line); //方法1 (改变了字符串本身) /* for (int i=0; i<len/2; i++) { tmp = line[i]; line[i] = line[len-1-i]; line[len-1-i] = tmp; } printf("逆转以后:%s\n", line); */ //方法2:不改变字符串 /* for (int i=len-1; i>=0; i--) { printf("%c", line[i]); } */ //用指针来重写方法2 char *p1 = line; char *p2 = p1 + len -1; for (char *p=p2; p>=p1; p--) { //p--,就相当于: p=p-1 printf("%c", *p); } return 0; }
指针与整数之间的加减运算
指针与指针之间的加减运算
良好的编码习惯:使用空指针
使用指针进一步优化端口管理,使代码更简明。
1.实现含有中文字符的字符串逆转
void reverse(unsigned char *s) { int len = strlen(s); unsigned char tmp[len+1]; unsigned char *p1 = s; unsigned char *p2 = tmp + len; *p2-- = 0; while (*p1) { if (*p1 < 0xA0) { //ASCII字符,一般都是小于等于127的。 *p2-- = *p1++; } else { *(p2-1) = *p1++; *p2 = *p1++; p2 -= 2; } } for (int i=0; i<len; i++) { s[i] = tmp[i]; } }