深度刨析C语言指针

Posted LC辞安

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深度刨析C语言指针相关的知识,希望对你有一定的参考价值。

指针的概念

1. 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。

2. 指针的大小是固定的4/8个字节(32位平台/64位平台)。

3. 指针是有类型,指针的类型决定了指针的+-整数的步长,指针解引用操作的时候的权限。

4. 指针的运算。

字符指针

在指针的类型中我们知道有一种指针类型为字符指针char*

第一种使用:

int main()

char ch = w;
char* pc = &ch;
//pc就是一个字符指针
*pc=w;
return 0;

第二种使用:

int main()

char arr[] = "abcdef";
char* pc = arr;//arr是首元素的地址
printf("%s\\n", arr);
printf("%s\\n", pc);
return 0;

深度刨析C语言指针_数组指针

int main()

char* pc = "abcdef";
//pc里存放的是‘a’的地址
printf("%s\\n", pc);
return 0;

深度刨析C语言指针_数组_02

int main()

char* pc = "abcdef";
//"abcdef"是常量字符串,不能改;
*pc = w;
printf("%s\\n", pc);
return 0;

深度刨析C语言指针_数组_03

例题:

int main()

char arr1[] = "abcdef";
char arr2[] = "abcdef";
char* p1 = "abcdef";
char* p2 = "abcdef";
if (arr1 == arr2)

printf("hehe\\n");

else

printf("haha\\n");

return 0;

深度刨析C语言指针_数组_04

这里p1和p2指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域,当几个指针。指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。所以arr1和arr2不同,p1和p2不同。

指针数组

概念:指针数组是一个数组,用来存放指针

int main()

int arr[10] = 0 ;//整形数组
char ch[5] = 0 ;//字符数组
int* parr[5];//存放整形指针的数组,指针数组;
char* parr[5];//存放字符指针的数组,指针数组;
return 0;

指针数组的使用:存放地址

深度刨析C语言指针_数组_05

指针数组的初级使用

int main()

int a = 10;
int b = 20;
int c = 30;
int d = 40;
int* arr[4] = &a,&b,&c,&d ;
int i = 0;
for (i = 0; i < 4; i++)

printf("%d ", *arr[i]);


return 0;

指针数组的一般使用

int main()

int arr1[] = 1,2,3,4,5 ;
int arr2[] = 2,3,4,5,6 ;
int arr3[] = 3,4,5,6,7 ;
int* parr[] = arr1,arr2,arr3 ;
int i = 0;
for (i = 0; i < 3; i++)

int j = 0;
for (j = 0; j < 5; j++)

printf("%d ", *(parr[i] + j));

printf("\\n");

return 0;

深度刨析C语言指针_i++_06

指针数组的内存布局


parr


int*

arr1

1,2,3,4,5

int*

arr2

2,3,4,5,6,

int*

arr3

3,4,5,6,7

数组指针

概念:是一种指针,存放数组的地址

int main()

int* p = NULL;//p是整形指针-指向整形的指针-存放整形的地址
char* pc = NULL;//pc是字符指针-指向字符的指针-存放字符的地址
//数组指针-指向数组的指针-存放数组的地址
// int arr[10]=0;
//arr首元素的地址
// &arr[0];首元素的地址
//&arr数组的地址
int arr[10] = 1,2,3,4,5,6,7,8,9,10 ;
int(*p)[10] = &arr;//数组的地址存放
//p就是一个数组指针
return 0;

int (*p)[10];

解释:p先和*结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫数组指针。

这里要注意:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。

数组指针的初级使用

通过下标打印

int main()

int arr[10] = 1,2,3,4,5,6,7,8,9,10 ;
int(*p)[] = &arr;
int i = 0;
for (i = 0; i < 10; i++)

printf("%d ", (*p)[i]);

return 0;

通过首元素向后访问打印

int main()

int arr[10] = 1,2,3,4,5,6,7,8,9,10 ;
int(*p)[] = &arr;
int i = 0;
for (i = 0; i < 10; i++)

printf("%d ", *(*p + i));//*p==arr *和&相互抵消了


return 0;
int main()

int arr[10] = 1,2,3,4,5,6,7,8,9,10 ;
int* p = arr;
int i = 0;
for (i = 0; i < 10; i++)

printf("%d ", *(p + i));



return 0;

对于一维数组的打印,整形指针就可以访问打印,使用数组指针有点大材小用,对于数组指针可以用来打印二维数组;

二维数组的一般打印

void print(int arr[3][5], int x, int y)

int i = 0;
for (i = 0; i < x; i++)

int j = 0;
for (j = 0; j < y; j++)

printf("%d ", arr[i][j]);

printf("\\n");



int main()

int arr[3][5] = 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7 ;
print(arr, 3, 5);
return 0;

二维数组通过数组指针打印

思路:将数组的第一行理解为数组的首元素

void print(int(*p)[5], int x, int y)

int i = 0;
for (i = 0; i < x; i++)

int j = 0;
for (j = 0; j < y; j++)

//printf("%d ", *(*(p + i) + j));
//相同的写法
//printf("%d ", (*(p + i))[j]);
//printf("%d ", p[i][j]);//p[i]==arr[i];
printf("%d ", *(p[i] + j));
//总结:*和[]相当于得到的是数组首元素的地址

printf("\\n");


int main()

int arr[3][5] = 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7 ;
print(arr, 3, 5);
return 0;

用一维数组辅助理解

int main()

int arr[10] = 1,2,3,4,5,6,7,8,9,10 ;
int* p = arr;
int i = 0;
for (i = 0; i < 10; i++)

//printf("%d ", arr[i]);
//printf("%d ", *(p + i));
//printf("%d ", *(arr + i));
printf("%d ", p[i]);//arr[i]==*(arr+i)==*(p+i)==p[i]


return 0;

辨析指针数组和数组指针

int arr[5]​:arr是一个5个元素的整形数组

int*parr1[10]​:parr1是一个数组,该数组有10个元素,每个元素的类型是int*,parr1是指针数组;

int(*parr2)[10]​:parr2是一个指针,该指针指向一个数组,数组有10个元素,每个元素的类型是int,parr2是数组指针;

int(*parr3[10])[5]​:因为[]的结合性比*的高,所以parr3是一个数组,该数组有十个元素,每个元素的类型是数组指针,该数组指针指向的数组有五个元素,每个元素的类型是int;

注:去掉数组名和[],剩下的是元素的类型

数组传参和指针传参

一维数组传参

void test1(int arr1[])

void test1(int arr1[10])

void test1(int* arr1)

void test2(int* arr2[10])

void test2(int**arr2)//arr2一级指针的地址,可以存放在二级指针中

int main()


int arr1[10] = 0 ;
int* arr2[10] = 0 ;
test1(arr1);
test2(arr2);


return 0;

二维数组传参

可以省略行不能省略列

void test(int arr[3][5])

void test(int arr[][5])

void test(int(*p)[5])

void test(int* arr);//err
void test(int** arr);//err
void test(int* arr[5]);//err
int main()

int arr[3][5] = 0 ;
test(arr);

return 0;

一级指针传参

void print(int* p)

int main()

int arr[10] = 0 ;
int* p = arr;
print(p);

return 0;

当一个函数的参数部分为一级指针的时候,函数能接收什么参数?

void test(int*p)

int main()

int a = 10;
int* p1 = &a;
test(&a);//ok
test(p1);//ok


return 0;

二级指针传参

void test(int**ptr)

int main()

int n = 20;
int* p = &n;
int** pp = &p;
test(pp);
test(&p);
return 0;

当函数的参数为二级指针的时候,可以接收什么参数?

void test(char**pc)

int main()

char c = w;
char* p = &c;
char** pp = &p;
char* arr[10];
test(pp);
test(&p);
test(arr);//ok

return 0;

函数指针

指向函数的指针---存放函数地址的一个指针

int Add(int x, int y)

return(x + y);

int main()

int a = 10;
int b = 20;
Add(a, b);
printf("%d\\n", Add(a, b));
//&函数名和函数名都是函数的地址
printf("%p\\n", &Add);
printf("%p\\n", Add);
//存放函数的地址
int(*pa)(int, int) = Add;//pa就是一个函数指针
printf("%d\\n", (*pa)(2, 3));
//另一种写法
printf("%d\\n", pa(2, 3));
return 0;

深度刨析C语言指针_数组指针_07

深入理解函数指针

来源:《C陷阱和缺陷》

深度刨析C语言指针_数组_08

解析

//(*(   void(*)()     ) 0)()
//把0强制类型转化为void(*)()函数指针类型,0就是一个函数地址,
//然后*调用0地址处的该函数
//void(          *signal(       int,    void(*)(int))        )(int)
//signal是一个函数声明,有两个参数,第一个是int,第二个是函数指针,该函数指针指向的
//函数参数是int,返回类型是void,signal函数的返回类型是一个函数指针,该函数指针指向的
//函数参数是int,返回类型是void
//可以通过typedef简化代码
typedef void(*pfun_t)(int);
pfun_t signal(int, pfun_t);

函数指针数组

存放函数的地址

int(*parr[4])(int,int)

函数指针数组的使用

int add(int x, int y)

return x + y;

int sub(int x, int y)

return x - y;

int mul(int x, int y)

return x * y;

int div(int x, int y)

return x / y;

int main()

int(*parr[4])(int, int) = add,sub,mul,div ;
int i = 0;
for (i = 0; i < 4; i++)

printf("%d ", parr[i](2, 3));

return 0;

深度刨析C语言指针_数组指针_09

通过函数指针数组模拟实现计算器

void menu()

printf("***********************************\\n");
printf("****1,Add 2.Sub*******\\n");
printf("****3.Mul 4.Div*******\\n");
printf("******* 0.exit **********\\n");
printf("***********************************\\n");


int Add(int x,int y)

return x + y;

int Sub(int x, int y)

return x - y;

int Mul(int x, int y)

return x * y;

int Div(int x, int y)

return x / y;

int main()

int input = 0;
int x = 0;
int y = 0;
int(*pfarr[])(int, int) = 0,Add,Sub,Mul,Div ;
do

menu();
printf("请选择:");
scanf("%d", &input);
if (input >= 1 && input <= 4)

printf("请选择两个操作数:");
scanf("%d%d", &x, &y);
int ret = (*pfarr[input])(x, y);
printf("%d\\n", ret);

else if (input == 0)

printf("退出\\n");

else

printf("选择错误\\n");


while (input);

return 0;

指向函数指针数组的指针

int (*pfarr[4])(int, int);
int(*(*ppfarr)[4])(int, int)=&pfarr;
//ppfarr是一个数组指针,指针指向的数组有四个元素
//指向的数组每个元素的类型是函数指针int(*)(int,int)

回调函数

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

void menu()

printf("***********************************\\n");
printf("****1,Add 2.Sub*******\\n");
printf("****3.Mul 4.Div*******\\n");
printf("******* 0.exit **********\\n");
printf("***********************************\\n");


int Add(int x, int y)

return x + y;

int Sub(int x, int y)

return x - y;

int Mul(int x, int y)

return x * y;

int Div(int x, int y)

return x / y;

int main()

int input = 0;
int x = 0;
int y = 0;
do

menu();
printf("请选择:");
scanf("%d", &input);
switch (input)

case 1:
printf("请选择两个操作数:");
scanf("%d%d", &x, &y);
int ret=Add(x, y);
printf("%d\\n", ret);
break;
case 2:
printf("请选择两个操作数:");
scanf("%d%d", &x, &y);
ret=Sub(x, y);
printf("%d\\n", ret);
break;
case 3:
printf("请选择两个操作数:");
scanf("%d%d", &x, &y);
ret=Mul(x, y);
printf("%d\\n", ret);
break;
case 4:
printf("请选择两个操作数:");
scanf("%d%d", &x, &y);
ret=Div(x, y);
printf("%d\\n", ret);
break;
case 0:
printf("退出\\n");
break;
default:
printf("选择错误\\n");
break;
printf("请选择两个操作数:");
scanf("%d%d", &x, &y);
int ret=Add(x, y);
printf("%d\\n", ret);

代码重复出现了多次,可以利用回调函数解决;

void menu()

printf("***********************************\\n");
printf("****1,Add 2.Sub*******\\n");
printf("****3.Mul 4.Div*******\\n");
printf("******* 0.exit **********\\n");
printf("***********************************\\n");


int Add(int x, int y)

return x + y;

int Sub(int x, int y)

return x - y;

int Mul(int x, int y)

return x * y;

int Div(int x, int y)

return x / y;

void Calc(int(*pf)(int, int))

int x = 0;
int y = 0;
printf("请选择两个操作数:");
scanf("%d%d", &x, &y);
int ret = pf(x, y);
printf("%d\\n", ret);

int main()

int input = 0;
do

menu();
printf("请选择:");
scanf("%d", &input);
switch (input)

case 1:
Calc(Add);
break;
case 2:
Calc(Sub);
break;
case 3:
Calc(Mul);
break;
case 4:
Calc(Div);
break;
case 0:
printf("退出\\n");
break;
default:
printf("选择错误\\n");
break;


while (input);

return 0;

初级冒泡排序:只能实现整数的排序

void Bubble_sort(int arr[], int sz)

//趟数
int i = 0;
for (i = 0; i < sz; i++)

//一趟冒泡排序
int j = 0;
for (j = 0; j < sz - 1 - i; j++)

if (arr[j] > arr[j + 1])

int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;




int main()

int arr[10] = 9,8,7,6,5,4,3,2,1,0 ;
int sz = sizeof(arr) / sizeof(arr[0]);
Bubble_sort(arr, sz);
int i = 0;
for (i = 0; i < sz; i++)

printf("%d ", arr[i]);

return 0;

qsort

void qsort( void *base, size_t num, size_t width, int ( *cmp )(const void *e1, const void *e2 ) );

第一个参数:目标数组的起始位置

第二个参数:数组的大小,单位是元素

第三个参数:元素的大小,单位是字节

第四个参数:函数指针(比较函数)

比较函数:第一个元素大于第二个元素返回大于0

相等返回0,第一个元素小于第二个元素返回小于0;

qsort库函数的实现

排序整形数组

#include<stdlib.h>
int cmp_int(const void* e1, const void* e2)

return *(int*)e1 - *(int*)e2;

void test1()

int arr[] = 9,8,7,6,5,4,3,2,1,0 ;
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), cmp_int);
int i = 0;
for (i = 0; i < sz; i++)

printf("%d ", arr[i]);


int main()

test1();

return 0;

深度刨析C语言指针_数组指针_10

关于void*的知识:​可以接受任意类型的地址;不能进行解引用操作;不能进行加减整数的操作

排序float型的数组

#include<stdlib.h>
int cmp_flo(const void* e1, const void* e2)

return ((int)(*(float*)e1 - *(float*)e2));

void test()

float f[] = 9.0,8.0,7.0,6.0,5.0,4.0,3.0,2.0,1.0 ;
float sz = sizeof(f) / sizeof(f[0]);
qsort(f, sz, sizeof(f[0]), cmp_flo);
int i = 0;
for (i = 0; i < sz; i++)

printf("%f ", f[i]);


int main()

test();

return 0;

深度刨析C语言指针_i++_11

排序结构体数组

按照年龄排序

#include<stdlib.h>
struct stu

char name[20];
int age;
;
int cmp_stu_by_age(const void* e1, const void* e2)

return ((struct stu*)e1)->age - ((struct stu*)e2)->age;

void test()

struct stu s[3] = "zhangsan",40,"lisi",30,"wangwu",20 ;
int sz = sizeof(s) / sizeof(s[0]);
qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
int i = 0;
for (i = 0; i < 3; i++)

printf("%s %d ", s[i].name, s[i].age);
printf("\\n");




int main()

test();

return 0;

深度刨析C语言指针_数组_12

按照名字排序

#include<stdlib.h>
#include<string.h>
struct stu

char name[20];
int age;
;
int cmp_stu_by_name(const void* e1, const void* e2)

return strcmp (((struct stu*)e1)->name , ((struct stu*)e2)->name);

void test()

struct stu s[3] = "zhangsan",40,"lisi",30,"wangwu",20 ;
int sz = sizeof(s) / sizeof(s[0]);
qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
int i = 0;
for (i = 0; i < sz; i++)

printf("%s %d", s[i].name, s[i].age);
printf("\\n");


int main()

test();

return 0;

深度刨析C语言指针_i++_13

模拟实现qsort

排序整形数组

int cmp_int(const void* e1, const void* e2)

return *(int*)e1 - *(int*)e2;

void Swap(char* buf1, char* buf2, int width)

int i = 0;
for (i = 0; i < width; i++)

char tmp =* buf1;
*buf1 = *buf2;
*buf2 = tmp;
buf1++;
buf2++;


void bubble_sort(void* base, int sz, int width, int(*cmp)( const void* e1,const void* e2))

//趟数
int i = 0;
for (i = 0; i < sz; i++)

//每一趟比较的对数
int j = 0;
for (j = 0; j < sz - 1 - i; j++)

//每个元素的比较
if (cmp((char*)base + j * width, (char*)base + (j+1) * width)>0);
//交换
Swap((char*)base + j * width, (char*)base + (j+1) * width,width);



void test()

int arr[10] = 9,8,7,6,5,4,3,2,1,0 ;
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
int i = 0;
for (i = 0; i < sz; i++)

printf("%d ", arr[i]);


int main()


test();

return 0;

排序结构体数组

struct stu

char name[20];
int age;
;
int cmp_stu_by_age(const void* e1, const void* e2)

return((struct stu*)e1)->age - ((struct stu*)e2)->age;

void Swap(char* buf1, char* buf2, int width)

int i = 0;
for (i = 0; i < width; i++)

char tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
buf1++;
buf2++;


void bubble_sort(void* base, int sz, int width, int(*cmp)(void* e1, void* e2))

int i = 0;
for (i = 0; i < sz-1; i++)

int j = 0;
for (j = 0; j < sz - 1 - i; j++)

if (cmp((char*)base + j * width, (char*)base + (j + 1) * width)>0);
Swap((char*)base + j * width, (char*)base + (j + 1) * width,width);



void test()

struct stu s[3] = "张三",40,"李四",20,"王五",10 ;
int sz = sizeof(s) / sizeof(s[0]);
bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_age);
int i = 0;
for (i = 0; i < sz; i++)

printf("%s %d", s[i].name, s[i].age);
printf("\\n");


int main()

test();

return 0;

指针和数字笔试题笔试题解析

一维数组

int a[] = 1,2,3,4;
int main()

printf("%d\\n", sizeof(a));
printf("%d\\n", sizeof(a + 0));
printf("%d\\n", sizeof(*a));
printf("%d\\n", sizeof(a + 1));
printf("%d\\n", sizeof(a[1]));
printf("%d\\n", sizeof(&a));
printf("%d\\n", sizeof(*&a));
printf("%d\\n", sizeof(&a + 1));
printf("%d\\n", sizeof(&a[0]));
printf("%d\\n", sizeof(&a[0] + 1));
return 0;

深度刨析C语言指针_i++_14

int main()


//字符数组
char arr[] = a,b,c,d,e,f;
printf("%d\\n", sizeof(arr));
printf("%d\\n", sizeof(arr+0));
printf("%d\\n", sizeof(*arr));
printf("%d\\n", sizeof(arr[1]));
printf("%d\\n", sizeof(&arr));
printf("%d\\n", sizeof(&arr+1));
printf("%d\\n", sizeof(&arr[0]+1));

return 0;

深度刨析C语言指针_数组指针_15

#include<string.h>
int main()

char arr[] = a,b,c,d,e,f ;
printf("%d\\n", strlen(arr));//随机值 strlen找\\0;
printf("%d\\n", strlen(arr + 0));//随机值
//printf("%d\\n", strlen(*arr));//err
//printf("%d\\n", strlen(arr[1]));//err
printf("%d\\n", strlen(&arr));//随机值
printf("%d\\n", strlen(&arr + 1)); //随机值
printf("%d\\n", strlen(&arr[0] + 1));//随机值

return 0;

深度刨析C语言指针_数组指针_16

int main()

char arr[] = "abcdef";
printf("%d\\n", sizeof(arr));
printf("%d\\n", sizeof(arr + 0));
printf("%d\\n", sizeof(*arr));
printf("%d\\n", sizeof(arr[1]));
printf("%d\\n", sizeof(&arr));
printf("%d\\n", sizeof(&arr + 1));
printf("%d\\n", sizeof(&arr[0] + 1));

return 0;

深度刨析C语言指针_数组_17

int main()

char arr[] = "abcdef";
printf("%d\\n", strlen(arr));
printf("%d\\n", strlen(arr + 0));
printf("%d\\n", strlen(*arr));
printf("%d\\n", strlen(arr[1]));
printf("%d\\n", strlen(&arr));
printf("%d\\n", strlen(&arr + 1));
printf("%d\\n", strlen(&arr[0] + 1));

return 0;

深度刨析C语言指针_i++_18

int main()

char* p = "abcdef";
//常量字符串p中存放的首元素的地址
printf("%d\\n", sizeof(p));
printf("%d\\n", sizeof(p + 1));
printf("%d\\n", sizeof(*p));
printf("%d\\n", sizeof(p[0]));
printf("%d\\n", sizeof(&p));
printf("%d\\n", sizeof(&p + 1));
printf("%d\\n", sizeof(&p[0] + 1));
return 0;

深度刨析C语言指针_i++_19

#include<string.h>
int main()

char* p = "abcdef";
printf("%d\\n", strlen(p));
printf("%d\\n", strlen(p + 1));
//printf("%d\\n", strlen(*p));//err
//printf("%d\\n", strlen(p[0])); //err
printf("%d\\n", strlen(&p));
printf("%d\\n", strlen(&p + 1));
printf("%d\\n", strlen(&p[0] + 1));
return 0;

深度刨析C语言指针_数组指针_20

二维数组

int main()


int a[3][4] = 0 ;
printf("%d\\n", sizeof(a));
printf("%d\\n", sizeof(a[0][0]));
printf("%d\\n", sizeof(a[0]));
printf("%d\\n", sizeof(a[0] + 1));
printf("%d\\n", sizeof(*(a[0] + 1)));
printf("%d\\n", sizeof(a + 1));
printf("%d\\n", sizeof(*(a + 1)));
printf("%d\\n", sizeof(&a[0] + 1));
printf("%d\\n", sizeof(*(&a[0] + 1)));
printf("%d\\n", sizeof(*a));
return 0;

深度刨析C语言指针_数组_21

指针笔试题

int main()

int arr[5] = 1,2,3,4,5 ;
int* ptr = (int*)(&arr + 1);
printf("%d\\n%d\\n", *(arr + 1), *(ptr - 1));
//*(arr+1)数组名表示首元素的地址+1,指向第二个元素,解引用得到第二个元素;
//ptr表示跳过整个数组,ptr-1表示指向第五个元素,解引用得到第五个元素
return 0;

深度刨析C语言指针_数组_22

struct Test

int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//假设结构体大小为20字节
int main()

p = (struct Test*)0x100000;
printf("%p\\n", p + 0x1);//p+1,取决与结构体类型,结构体指针大小是二十个字节
//加1,就是跳过20个字节,0x100000+20=0x100014
printf("%p\\n", (unsigned long)p + 0x1); //结构体类型强转化为unsigned long
//加1表示跳过1个字节0x100000+1=0x100001;
printf("%p\\n", (unsigned int*)p + 0x1);//结构体类型被强转化为unsigned int*
//加1就是跳过4个字节 0x100000+1=0x100004

return 0;

深度刨析C语言指针_数组指针_23

int main()

int a[4] = 1, 2, 3, 4 ;
//该数组在内存中的存储形式:小端存储:01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00
int* ptr1 = (int*)(&a + 1);
//&a取出的是数组的地址,+1跳过整个数组,强转化为int*,存放在ptr中
int* ptr2 = (int*)((int)a + 1);
//数组名表示首元素的地址,用int强转化为整数加1,在用int*强转化为地址,地址加1就是跳过一个字节
printf("%x,%x", ptr1[-1], *ptr2);
//ptr[-1]=(ptr+(-1))=(ptr-1);
//ptr 00 00 00 02 小端形式存储进去,再原来的形式拿出来 20 00 00 00
return 0;

深度刨析C语言指针_数组_24

int main() 

int a[3][2] = (0, 1), (2, 3), (4, 5) ;
int* p;
p = a[0];
printf("%d", p[0]);
return 0;

深度刨析C语言指针_数组_25

int main() 

int aa[2][5] = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ;
int* ptr1 = (int*)(&aa + 1);
int* ptr2 = (int*)(*(aa + 1));
printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
return 0;

深度刨析C语言指针_数组_26

int main()

char* a[]= "work","at","alibaba" ;
//指针数组 存放的w a a的地址
char** pa = a;
pa++;//指针加1 指向第二个字符串
printf("%s\\n", *pa);//at
return 0;

深度刨析C语言指针_数组指针_27

有错的地方请大佬指正

继续加油

以上是关于深度刨析C语言指针的主要内容,如果未能解决你的问题,请参考以下文章

C语言动态开辟指针的指针问题

C 语言----- 指针

浅谈C语言的动态内存开辟

C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针

详细刨析C语言数据的储存

详细刨析C语言数据的储存