C语言补充:指针的基础理解
1.int* 和 char* 的修改字节上的区别及指针的运算
先看两段代码:
int a = 0x11223344; int* pa = &a; *pa = 0;
int a = 0x11223344; char* pa = &a; *pa = 0;
这里我们不难发现对于指针的改变其实是取决于对应的指针类型的,32位环境下char就是一个字节,而int为4个字节
知道了这一点之后我们就可以对指针+/-数实际上就是跳过对应的字节
int main() { int arr[5] = { 1,2,3,4,5 }; int sz = sizeof(arr) / sizeof(arr[0]); int* p = &arr[0]; for (int i = 0; i这就是指针加上数字,那么指针-指针有什么意义吗
其实可以类比成日期-日期就能算到中间差几天,那么指针就是中间差的元素数
例如:用char*类型计算字符中间的差值
int my_strlen(char* p) { char* p1 = p; while (*p != '\0') { p++; } return p - p1;//指针-指针 } int main() { char arr[] = "abcdef"; int len = my_strlen(arr); printf("%d", len); return 0; }2.const的对变量和指针的作用
int main() { const int n = 10; //n = 0; //err n无法改变 //arr[n]; //err n为常量就不会报错 int* p = &n; *p = 0; printf("%d", n); //n=0 return 0; }由此我们可以看出对于变量的限制并不会使变量改变成常量,而且可以通过指针的方式让变量改变
而对指针的修饰有两种
int main() { int a = 0; int b = 10; const int* p = &a; p = &b; //*p = 10; //err int* const ps = &a; //ps = &b; //err *ps = 10; return 0; }3.传值调用和传址调用
传值调用:仅仅使用值
void Swap(int x, int y) { int z = 0; z = x; x = y; y = z; } int main() { int a = 10; int b = 20; printf("交换前:%d,%d\n", a, b);//交换前:10, 20 Swap(a, b); printf("交换后:%d,%d\n", a, b);//交换后:10, 20 return 0; }传址调用:要对传过去的值进行修改
void Swap(int* x, int* y) { int z = 0; z = *x; *x = *y; *y = z; } int main() { int a = 10; int b = 20; printf("交换前:%d,%d\n", a, b);//交换前:10, 20 Swap(&a, &b); printf("交换后:%d,%d\n", a, b);//交换后:20,10 return 0; }4.数组名的理解
数组名一般就是首元素的地址除了以下几种情况:
int main() { int arr[10]; int* p = arr; int sz = sizeof(arr) / sizeof(arr[0]); for (int i = 0; i *(p + i)=p[i] } return 0; }这里以将arr[1]和*(arr+1)认为是一致的那我们就可以认为平时的传数组调用了
void size_arr(int arr[]) { //void size_arr(int* arr) int sz = sizeof(arr) / sizeof(arr[0]); //1 printf("%d", sz); } int main() { int arr[] = { 1,2,3,4,5,6,7,8,9 }; int sz = sizeof(arr) / sizeof(arr[0]); printf("%d\n", sz); //9 size_arr(arr); return 0; }5.冒泡排序
int main() { int arr[8] = { 7,6,5,4,3,2,1,0 }; int sz = sizeof(arr) / sizeof(arr[0]); for (int i = 0; i第一个循环:将一个数据放到正确的位置,最坏的情况要跑sz-1次
第二个循环:sz-1是为了交换sz-1个数据,-i是为了减去已经放置好的数据
这里可以优化:
int main() { int arr[8] = { 7,6,5,4,3,2,1,0 }; int sz = sizeof(arr) / sizeof(arr[0]); for (int i = 0; i6.qsort函数的使用
我们使用排序是不一定总是在比较整形,如果是字符串类型或结构体那么就可以使用到去qsort函数了
使用时我们要知道4个参数:
- void* base 指针指向要排序的第一个数组
- size_t num base指向的待排序的元素数组个数
- size_t size base指向待排序元素的大小
- int * (compar) (const void *, const void *) 函数指针指向的是如何比较元素的函数
函数的返回值:
p1>p2 返回>0的数
p1=p2 返回0
p1 //p1p2 返回0的数 //p1=p2 返回0 //p1 int arr[] = { 9,8,7,6,5,4,3,2,1,0 }; int sz = sizeof(arr) / sizeof(arr[0]); qsort(arr, sz, sizeof(int), Cmp_int); for (int i = 0; i name); } int Cmp_sturct_by_age(const void* e1, const void* e2) { return ((struct Stu*)e1)->age - ((struct Stu*)e1)->age; } void test02() { struct Stu arr[3] = { {"zhangsan",20},{"lisi",35},{"wangwu",18} }; int sz = sizeof(arr) / sizeof(arr[0]); qsort(arr, sz, sizeof(arr[0]), Cmp_struct_by_name); }