一、指针
1.1指针的相关概念、
指针:指向变量地址的类型
指针变量:指向变量地址的变量
地址:内存单元的编号就是地址
1.2指针的定义格式
变量类型 *变量名;
void *;万能指针
1.3指针占用内存的大小
在32位系统上指针占4个字节
64位系统上指针占8个字节
1.4指针相关的*和&(取址)符号
&:获取变量的地址
*:代表取地址中的内容,定义的时候char *p中的*只起到一个标识的作用,表示p是一个指针
1.5指针的基本用法
向地址中写入值
unsigned int *p = (unsigned int *)地址;#用强制类型转换将地址转换为和指针相同的类型,
*p = 新的值
eg:
向0xaabbccdd地址中写入0x12345678的值。
unsigned int *p = (unsigned int *)0xaabbccdd;
*p = 0x12345678;
1.6指针加1和减1问题
#include <my_head.h>
int main(int argc, const char *argv[])
{
int a = 10;
int *p = NULL;
p = &a;
*p = 50;
printf("p+1 = %p, &a = %p\n", p+1 , &a);
return 0;
}
运行结果:
linux@ubuntu:~/DC101/01drivers/0329$ gcc main.c
linux@ubuntu:~/DC101/01drivers/0329$ ./a.out
p+1 = 0x7ffdd2831510, &a = 0x7ffdd283150c
linux@ubuntu:~/DC101/01drivers/0329$
0x10-0x0c = 0x04
// 指针加1移动的字节数,等于它指向类型所占的字节数
// char *p; //p+1移动1字节
// int *p; //p+1移动4字节
// short *p; //p+1移动2字节
// long *p; //p+1移动8字节
printf("p-1 = %p,&a = %p\n", p - 1, &a);
// 指针减1移动的字节数,等于它指向类型所占的字节数
// char *p; //p-1移动1字节
// int *p; //p-1移动4字节
// short *p; //p-1移动2字节
// long *p; //p-1移动8字节
1.7指针相减
#include <my_head.h>
int main(int argc, const char *argv[])
{
int a = 10;
int *p = NULL;
p = &a;
*p = 50;
long b = 40;
long *q = NULL;
q = &b;
*q = 80;
printf("(p+1) - p = %ld\n", (p+1) - p);
printf("(long)(p+1) - (long)p = %ld\n", (long)(p+1) - (long)p);
printf("(q+1) - q = %ld\n", (q+1) - q);
return 0;
运行结果:
linux@ubuntu:~/DC101/01drivers/0329$ gcc main.c
linux@ubuntu:~/DC101/01drivers/0329$ ./a.out
(p+1) - p = 1
(long)(p+1) - (long)p = 4
(q+1) - q = 1
在 C 语言中,指针之间的差值计算通常用于计算两个指针之间相隔的元素个数,而不是直接得到字节偏移量。指针相减的结果是一个整数值,表示两个指针之间相隔的元素个数,而不是字节偏移量。
二、指针和一维数组之间的关系
int arr[3] = {111, 222, 333}
arr[0]:
&arr[0]:
arr:
&arr:
arr[0]+1:
&arr[0]+1:
arr + 1:
&arr + 1:
arr[0] ++:
&arr[0] ++:
(&arr[0])++:
arr ++:
&arr ++:
(&arr)++:
arr[0]:
第0个元素,它的类型是int,arr[0]是变量(arr[0]++)。
&arr[0]:
对第0个元素取地址,它的类型是(int *),它是一个常量不能((&arr[0])++)
arr:
它是一维数组的首地地址,它的指针类型是(int *),它是一个常量不能(arr++)。
&arr:
对整个数组取地址,它的指针类型是(int (*)[3] ),它是一个常量((&arr)++).
arr[0]+1:
将arr[0]的值取出和1做加法运算,结果是112.
&arr[0]+1:
移动了4字节(int)的大小,(int *)
arr+1
:移动了4字节(int)的大小,(int *)
&arr+1
:移动了12字节(int [3])的大小,(int (*)[3])
arr[0]++
:相当于是让第0个元素的值加1,赋值给了arr[0]
&arr[0]++:
错误写法,常量不能取地址
(&arr[0])++:
错误写法,常量不能自加
arr++
:错误写法,常量不能自加
&arr++:
错误写法,常量不能取地址
(&arr)++:
错误写法,常量不能自加
int a = 10; &a = 0x111;
int *p = &a;
p:
*p:
&p:
p+1:
*p+1:
&p + 1:
p++:
*p++:
(*p)++:
&p++:
(&p)++:
p:
指针变量,它的类型是(int *)
*p:
取地址中的内容,它的类型是(int),它是变量可以自加((*p)++)
&p:
取指针变量p的地址,它类型是(int **),它是常量
p+1:
移动了4字节,移动了(int)大小
*p+1:
取出p指向内存中的数值,然后加了1,内存中的数值没有改变
&p+1:
移动了8字节,移动了(int *)大小
p++:
移动了4字节,指向了下一个int变量的地址
*p++:
相当于取出*p,然后p++,p指向下一个int变量的地址。(p是地址变量,p++是地址常量,可以对它取*)
(*p)++:
相当于让p指向内存中的值做了自加1的操作。
(p是地址变量,p++是地址常量,常量不能取地址)&p++:
错误写法,常量不能取地址
(&p)++:
错误写法,常量不自加
指针类型相同,指针加1移动大小也相同,此时可以直接划等号
int arr[3] = {111,222,333};
int *p;
p = arr;
p = &arr[0];
arr[i]<=>*(arr+i)<=>*(p+i)<=>p[i]
三、sizeof与srlen有什么区别
- sizeof是关键字,而strlen是函数。
- sizeof是求类型所占内存的大小,strlen求字符数组中字符的个数,strlen使用的时候必须有'\0'。
- sizeof计算字符串长度会加 ’\0‘
char arr[] = "hello";
sizeof(arr) = 6
strlen(arr) = 5
char arr[100] = "hello";
sizeof(arr) = 100
strlen(arr) = 5
char arr[] = {'h','e','l','l','o'};
sizeof(arr) = 5
strlen(arr) = 大小不能确定,没有'\0'
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
sizeof(arr) = 40;
strlen((char *)arr) = 1