最小单元(1字节byte)
的编号
,也就是地址
口语
中说的指针,通常指的是指针变量
,是用来存放内存地址的变量&(取地址操作符)
取出变量的内存 (起始地址
),把地址可以存放到一个变量中,这个变量就是指针变量int a = 10;
int * pa = &a;
*pa = 20;
printf("%d\n", a);
20
存放在指针中
的值都被当成地址
处理32位
的机器,假设有32根地址线
,那么假设每根地址线在寻址的时候产生高电平(高电压
)和低电平(低电压)
就是(1或者0
),有2的32次方个地址. 在32位
的机器上,地址是32个0或者1
组成二进制序列,那地址就得用4个字节的空间来存储,所以一个指针变量的大小就应该是4个字节
.那如果在64位
机器上,如果有64个地址线,那一个指针变量的大小是8个字节
,才能存放一个地址。指针的定义方式是:type + *
int* pa;
char* pc;
float* pf;
printf("%d\n", sizeof(pa));
printf("%d\n", sizeof(pc));
printf("%d\n", sizeof(pf));
4
4
4
在x86下,指针变量的大小都是4.
2.1 指针±整数int main()
{int a = 0x11223344;
//int*pa = &a;
//*pa = 0;
char* pc = &a;
*pc = 0;
return 0;
}
因为用char*
,解引用的时候只能访问1个字节
,只能修改44
.
int main()
{int a = 0x11223344;
int* pa = &a;
char* pc = &a;
printf("pa=%p\n", pa);
printf("pc=%p\n", pc);
printf("pa+1=%p\n", pa -1);
printf("pc+1=%p\n", pc -1);
return 0;
}
pa=00AFF7EC
pc=00AFF7EC
pa+1=00AFF7E8 //减4
pc+1=00AFF7EB //减1
int arr[10] = {0 };
int* p = arr;//数组名就是数组首元素的地址arr->&arr[0];
for (int i = 0; i< 10; i++)
{*(p + i) = i + 1;
}
int arr[10] = {0 };
char* p = arr;
int i = 0;
for (i = 0; i< 10; i++)
{*p = i + 1;
p++;
}
可以看见用char
类型解引用整型数组是不对的.01 02 03 04
对应arr[0] = 67305985
.
野指针就是指针指向的位置是不可知
的(随机的、不正确的、没有明确限制的)
int* p;
*p = 20;
3.2 指针越界访问int main()
{int arr[10] = {0};
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
int* p = arr;
for (i = 0; i<= sz; i++)
{*p = i;
p++;
}
return 0;
}
Run-Time Check Failure #2 - Stack around the variable 'arr' was corrupted.
int* test()
{int num = 100;
printf("%p\n", &num);
return #
}
int main()
{int* p = test();
*p = 200;
printf("%d\n", *p);
printf("%p\n", p);
return 0;
}
010FF754
200
010FF754
3.4 避免野指针int main()
{int a = 10;
int* pa = &a;
int* p = NULL;
return 0;
}
int a = 10;
//int* p = NULL;
//*p = 20;
int* p = &a;
if (p != NULL)
{printf("%d\n", *p);
}
10
4 指针运算
4.1 指针±整型double arr[5] = {0};
double* p = arr;
int i = 0;
for (i = 0; i< 5; i++)
{printf("%lf ", *(p + i));
}
0.000000 0.000000 0.000000 0.000000 0.000000
浮点
用%f
#define N_VALUES 5
float values[N_VALUES];
float* vp;
int main()
{for (vp = &values[N_VALUES - 1]; vp >= &values[0]; vp--)
{*vp = 1;
}
for (int i = 0; i< N_VALUES; i++)
{printf("%f\n", values[i]);
}
return 0;
}
1.000000
1.000000
1.000000
1.000000
1.000000
实际在绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这样写,因为标准并不保证它可行。
4.2 指针减指针两个指针相减的前提是:指针指向的同一块连续的空间
int arr[10] = {0};
printf("%d\n", &arr[9] - &arr[0]);
printf("%d\n", &arr[0] - &arr[9]);
int a = 10;
char c = 'w';
printf("%d\n", &a - &c);//err
9
-9
2
5 指针和数组int my_strlen1(char* str)
{int count = 0;
while (*str)
{count++;
str++;
}
return count;
}
int my_strlen2(char* str)
{char* start = str;
while (*str)
str++;
return str - start;
}
//
int main()
{char arr[] = "abc";
int len1 = my_strlen1(arr);
int len2 = my_strlen2(arr);
printf("%d\n", len1);
printf("%d\n", len2);
return 0;
}
3
3
int arr[10] = {1,2,3,4,5,6,7,8,9,10 };
int* p = arr;
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i< sz; i++)
{printf("%d\n", *(p + i));
}
1
2
3
4
5
6
7
8
9
10
6 二级指针int main()
{int a = 10;//
int* p = &a;//
int** pp = &p;//
//*(*pp) = 200;
**pp = 200;
//*p = 20;
printf("%d\n", a);
return 0;
}
200
7 指针数组指针数组是指针还是数组?答案:是数组
。是存放指针的数组。
int arr[10];
char arr2[5];
int* arr3[5];//存放整型指针的数组
char* arr4[6];//存放字符指针的数组
int a = 10;
int b = 20;
int c = 30;
int d = 40;
int e = 50;
int* arr3[5] = {&a, &b, &c, &d, &e};//存放整型指针的数组
int i = 0;
for (i = 0; i< 5; i++)
{printf("%d ", *(arr3[i]));
}
10 20 30 40 50
int arr1[] = {1,2,3,4,5 };
int arr2[] = {2,3,4,5,6 };
int arr3[] = {3,4,5,6,7 };
int arr4[] = {4,5,6,7,8 };
int* arr[4] = {arr1, arr2, arr3, arr4};
int i = 0;
for (i = 0; i< 4; i++)
{int j = 0;
for (j = 0; j< 5; j++)
{ printf("%d ", *(*(arr+i)+j));
}
printf("\n");
}
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
上面的打印
可以写为
int i = 0;
for (i = 0; i< 4; i++)
{int j = 0;
for (j = 0; j< 5; j++)
{ printf("%d ", arr[i][j]);
}
printf("\n");
}```
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧