一、指针运算
//*p 代表的是它所指向的地制上面的值的运算
//p++ 是p 指针变量++,结果就是:p指向它的下一个地址
int main(){
int a = 10;
int *p = &a; //申明一个int类型的指针变量 p //&a取变量a的地址
*p = *p + 10; //p指向的是a在内存的地址,*p是取地址上的值, a = a + 10 a = 20;
printf("p:%d, a:%d\n",p,a);
int y = 1 + *p; // p指向的是a在内存的地址,*p是取地址上的值 y = 1+a = 21
printf("y:%d \n", y);
*p += 1; //将地制所指向的值+1 再付给自己 相当于 现在 a+=1 a = 21;
printf("p:%d, a:%d\n", p, a);
(*p)++; //将*p所指向的值 a++ ; a = 22
printf("p:%d, a: %d , p address: %#x \n",*p,a,p);
//将p的地址位移 根据运算符的优先级 先进行 ++ 运算 再进行 *p运算(不要轻易的执行这样的运算,因为你得出的这一个新地址不知道是谁在使用)
//p是int类型指针变量,*p++ = *(p++) ,p存储的是a的内存地址,p++是地址做偏移,然后*p再取了一个新的地址上面的值.
*p++;
printf("p:%d, a: %d , p address: %#x \n", *p, a, p);
system("pause");
return 0;
}
二、数组与指针
//例`:
int main(){
int a[5];
int *p = a;//数组名a,就是数组的首地址 所以可以直接赋值
int i;
printf("%#x\n",a);
//a+5,表示a 移动到数组的第5个位置 按照地址移到五个地址的长度
//p++ 指针位移
for (i = 0; p < a + 5;p++){
*p = i; //给指针所指的值赋值,相当于给数组a 赋值
i++;
}
system("pause");
return 0;
}
//例2:
int main(){
int a[5] = {1,2,3,4,5};
int *p = a;//数组名a,就是数组的首地址 所以可以直接赋值
int i;
printf("%#x\n",a);
p = p + 1; // 等价于 p++
printf("p:%d\n",*p);
//以下几个操作是相等的
//a[i] == *(p + i)
//&a[i] == a + i;
//p + i == &a[i] ==a+i
system("pause");
return 0;
}
三、指针和函数参数
java中:
int a = 10;
int b = a;//是将a对象所指向的引用的赋给b,所以b = 10;
C/C++中:
void swap(int c,int d){
int temp;
temp = c;
c = d;
d = temp;
}
int main() {
int a = 10;
int b = 5;
swap(a,b);
//因为C/C++中,相当于将a和b的值一份给函数swap()的参数c和d,c和d也会有一个新的内存地址,但是a和b的内存地址还是不会变的,他们的值也不变
printf(" a = %d,b = %d\n" , a, b); //a = 10 ,b = 5,
}
//实际上方法参数传递的时候是将a的值赋给d 将b 的值赋给e
//d跟e进行了交换 对a跟b完成没有关系
void swap(int d,int e){
printf("d address :%#x ,e address:%#x \n", &d, &e);
int temp;
temp = d;
d = e;
e = temp;
}
//行参的修改不能带来这个实参的修改
//将a b 的地址copy给了 形参 ,然后,将这份copy的地址进行了切换,而地址所指向的值是没有变的
void swap2(int *a, int *b){
printf("a address :%#x ,b address:%#x \n", a, b);
int *temp;
temp = a; //a的 地址给了temp
a = b; //a 地址变成了b的地址
b = temp; //将b的地址变成了a的地址
printf("a address :%#x ,b address:%#x \n", a, b);
}
void swap3(int *a, int *b){
int temp;
temp = *a; //将地址对应的值取出来 赋给temp
*a = *b; //将b地址所在的值 赋给了a地址所在的值
*b = temp; //将temp里面的值 赋给 b地址所在的值
}
int main(){
int a, b;
a = 10;
b = 5;
printf("a address :%#x ,b address:%#x \n", &a, &b);
//这样的方式只是将a跟b的值赋给了swap方法的参数不能将a和b的值进行交换
swap(a, b);
printf("a=%d,b=%d\n",a,b);
//swap2方法中的a 存的是一个地址的副本 达不到修改的值效果
swap2(&a, &b);
printf("a=%d,b=%d\n", a, b);
//此方法完成了a b 的交换
swap3(&a, &b);
printf("a=%d,b=%d\n", a, b);
system("pause");
return 0;
}
四、指针数组
#include "string.h"
void sort(char *name[],int n);
int main(){
//指针数组 :是一个数组,数组里面存放的是指针类型的变量
char *name[] = {"hello","hubin","axoo","world"};
int i, n = 4;
//给字符串排序
sort(name, n);
for (i = 0; i < n; i++){
printf("%s\n", name[i]);
}
//数组指针:是一个指针,这个指针指向的是一个数组的首地址
//p2是一个指针变量名
//p2指向的是一个数组,一个有5个元素的数组
char(*p2)[5]; //定义了一个数组指针
system("pause");
return 0;
}
//冒泡排序
//参数,是char类型的指针数组
//name[i] 是一个指针
void sort(char *name[], int n){
char *temp;
int i, j;
for (i = 0; i < n; i++){
for (j = 0; j< n - 1 - i; j++){
if (strcmp(name[j],name[j+1])>0){ //根据字母进行比较 相等返回 0
temp = name[j]; //将指针进行了切换
name[j] = name[j + 1];
name[j + 1] = temp;
}
}
}
}
五、 二级指针
int main(){
int a = 100;
int *p;
p = &a;
int **p2;
p2 = &p;
//二级指针 ,存的内容是一个一级指针的地址
//p的值就是p这个变量,这个变量保存的是a的地址
//*p 运算,得到的就是a的值
//*p2 运算,得到的就是p的值
//**p2 运算,得到的就是p的值的 *运算得到的值 a;
return 0;
}
六、知识要点
1、C语言中的函数如何调用?
1)先申明函数才能调用
int function(){
return 0;
}
int main(){
function()
return 0;
}
2)如果函数体再后面也要先申明才可调用
int function();
int main(){
function()
return 0;
}
int function(){
return 0;
}
2、头文件的引入和定义
系统定义的头文件是使用<> 引入 如:#include <stdlib.h>
自定义的头文件是使用 "" 引入 如: #include "hubin.h"
1)创建源文件 hubin.c 里面定义一个fun函数
#include "hubin.h"
void int fun(int a ){
return a++;
}
2)创建头文件 hubin.h 定义方法函数
void ing fun(int a);
3)引入自定义的头文件调用fun()函数
#include "hubin.h"
int main(){
int a = 0;
fun(a);
return 0;
}
3、运算符的优先级
4、p 和 *p 有什么区别
int main(){
int *p;
//p是一个指针变量名
//*p 是从p指针变量里面取出一个int 型数据
}
5、为什么会有 int *p 和 char *cp 的类型定义
指针变量都是用于存地址的,而地址都是用4个字节的数字表示的,
所以指针变量都是占用4个字节
p++ cp++ 的运算会随着指针的类型位移的距离不同
p++位移4个字节
cp++ 位移一个字节
正是因为有这样的区别 所以我们指针要有类型的却别定义