指针的常见操作
指针变量,有两方面的意思
- 一个指针指向的内容(数据值,一级)
指针变量本身存储的数据 (地址值)
#include <stdio.h> int main() { int a =10; int b = 0 ; int c =50; int *p = NULL; int *q = NULL; p = &a; // 对指针变量本身进行修改 p做 左值 // 对指针指向的数据 进行操作 b = *p ;// 通过地址获得地址中数据, 相当与是对 a变量的读取 *p = 20;// 把需要写入的数据,通过地址,写入对应的内存 ,对a 变量的写入 *p做 左值 p = &c; // p变量本身发生变化,与c变量关联 b = *p; // 对c变量读取操作 *p做 右值 *p = 10; //对 c变量的写入操作 q = p;// 把p指向的地址,赋值给q。p,q 指向同一个变量了c。 p做 右值 return 0; }赋值运算符的左右值
p做左值对指针变量本身进行修改, 存储某个变量的地址
p做右值把p指向的地址,赋值给另外一个指针。p,另一个 指向同一个变量了。
*p做左值向指针指向的变量 写入数据
*p做 右值读出向指针指向的变量的数据
指针作为参数 ,传参
函数传递参数
值传递, 在主调函数中,实参,在被调函数中,形参。 形参可以读出实参的数据。但是不能修改实参的值。
地址传递。 在主调函数中,实参,在被调函数中,形参。 形参可以通过间接访问的方式,读写实参的数据。实参和形参,都是指针。这两个指针中存储的地址值,同一个变量的地址。
函数使用指针作为参数
- 第一种情况,需要形参修改实参的情况。需要被调函数修改主调函数中数据的值
- 函数的返回值只有一个。 在被调函数中,需要返回多个数据的话,就需要传递值指针。因为在被调函数中可以修改主调函数的参数的只
void swap2(int * pa,int *pb) //地址传递 { int t = *pa; *pa = *pb; *pb =t; } int main() { int a =1; int b =2; //swap(a,b); swap2(&a,&b); printf("a is %d,b is %d\n",a,b); // 指针可以指向 任意0-4G地址 。但是不一定能读写,内存有保护机制 // (int*)0x2000 强制类型转换, 把2000 不当数字看,当地址看 int * p = (int*)0x2000; }指针和数组的关系
- 数组名是一个指向数组第一元素的指针常量(指针本身的值,不能发生变化。 指针是保存地址的变量,指针保存的地址,不能发生变化)。
- 数组名的类型 ,int a[] ; 类型 int [] ;int [ ] ≈ int *
- int [ ] ≈ int * ; c语言中,兼容类型。大部分可以相互替换,但是有例外。
不同点:
sizeof() int* --> 8byte int a[20] - > 20*sizeof(int) 80byte
在执行 取地址操作
int*p -> & -> int **(二级指针,地址的地址)
int a[10] -> & -> int (*p)[10] (数组指针)
int a[10] ; 对于数组名a 来说,可以把他想成一个指针变量 。 本质, a 是数组中第一个元素地址的别名
一维数组做参数
// int fill_array(int a[],int size) int fill_array(int *a, int size) { int i = 0; for(i=0;i<size;i++) { a[i] = rand()%50; } for (i = 0; i < size; i++) { *(a + i) = rand() % 50; } return 0; }一维字符数组做参数
//void show_str(char a[]) void show_str(char *a) { int i = 0 ; /* while('\0'!=a[i]) { printf("%c",a[i]); i++; } printf("\n"); */ while('\0'!=*(a+i) ) { printf("%c",*(a+i)); i++; } printf("\n"); while('\0'!=*a) { printf("%c",*(a++)); } printf("\n"); }