指针一句话就是存储地址的一个变量,当你想要拿到一个地址就需要用到&运算符。
如果要拿数组的地址就不用&运算符,因为数组名就是数组首元素的地址。
int main()
{
int pa=0;
int* p=&pa;
int arr[3]={1,2,3};
int* q=arr;
printf("%d",*p);
printf("\n");
for(int i=0;i<3;i++)
{
printf("%d ",*(q+i));
}
return 0;
}
这⾥pa左边写的是 int* , * 是在说明pa是指针变量,⽽前⾯的 int 是在说明pa指向的是整型(int)类型的对象。
通过解引用操作符(*)找到指向的地址,然后进行一系列操作
*pa 的意思就是通过pa中存放的地址,找到指向的空间,*pa其实就是a变量了。
指针变量的⼤⼩
#include <stdio.h>
//指针变量的⼤⼩取决于地址的⼤⼩
//32位平台下地址是32个bit位(即4个字节)
//64位平台下地址是64个bit位(即8个字节)
int main()
{
printf("%zd\n", sizeof(char *));
printf("%zd\n", sizeof(short *));
printf("%zd\n", sizeof(int *));
printf("%zd\n", sizeof(double *));
return 0;
}
注意指针变量的⼤⼩和类型是⽆关的,只要指针类型的变量,在相同的平台下,⼤⼩都是相同的。
指针±整数
#include <stdio.h>
int main()
{
int n = 10;
char *pc = (char*)&n;
int *pi = &n;
printf("%p\n", &n);
printf("%p\n", pc);
printf("%p\n", pc+1);
printf("%p\n", pi);
printf("%p\n", pi+1);
return 0;
}
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int len=sizeof(arr)/sizeof(arr[0]);
int* p=arr;
for(int i=0;i<len;i++)
{
printf("%d ",*(p+i));
}
return 0;
}
char* 类型的指针变量+1跳过1个字节, int* 类型的指针变量+1跳过了4个字节。
这就是指针变量的类型差异带来的变化。可以通过指针加减整数输出数组里面的所有元素。
指针-指针
#include <stdio.h>
int my_strlen(char *s)
{
char *p = s;
while(*p != '\0' )
p++;
return p-s;
}
int main()
{
printf("%d\n", my_strlen("abc"));
return 0;
}
指针-指针等于两个地址之间元素的个数,前提是必须是指向的同一块内存空间。
const修饰指针
const修饰左边
int main()
{
//const修饰左边
int n = 10;
int m = 20;
const int* p = &n;
*p = 20;//报错
p = &m; //可以
return 0;
}
const修饰右边
int main()
{
int n = 10;
int m = 20;
int *const p = &n;
*p = 20;//可以
p=&m;//报错
return 0;
}
const既修饰左边又修饰右边
int main()
{
int n = 10;
int m = 20;
int const * const p = &n;
*p = 20; //报错
p = &m; //报错
return 0;
}
const如果放在的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。但是指针变量本⾝的内容可变。
const如果放在的右边,修饰的是指针变量本⾝,保证了指针变量的内容不能修改,但是指针指向的内容,可以通过指针改变。
const两边都修饰既定值又定向。
结论就是左定值右定向
assert断言。
在使用指针之前应该判断指针是否为空指针,这是我们就可以用上assert断言。
assert.h 头⽂件定义了宏 assert() ,⽤于在运⾏时确保程序符合指定条件,如果不合,就报错终⽌运⾏。这个宏常常被称为“断⾔”。
assert(p != NULL);
验证变量 p 是否等于 NULL 。如果确实不等于 NULL ,程序继续运⾏,否则就会终⽌运⾏,并且给出报错信息提示。
当我们需要取消断言的时候可以定义一个宏
#define NDEBUG
然后,重新编译程序,编译器就会禁⽤⽂件中所有的 assert() 语句。如果程序⼜出现问题,可以移除这条 #define NDBUG 指令(或者把它注释掉),再次编译,这样就重新启⽤了 assert() 语句。这个宏定义#define NDEBUG必须写在代码的第一行