指针类型的理解.
1.内存中房间号(地址)是什么(指针变量中存的数据)
2.对应的房间号多大.(指针的类型之中)
char* 和 int* 两种不同的类型,不能互相赋值.
一种特殊的类型,void*(不是空指针):只考虑指针的地址是啥,不考虑这块内存的大小.
void* 不能进行解引用,如果有些函数需要同时处理多种类型的指针的时候,使用 void* 就比较合适.
例如 memste (传数组把某片连续空间设成某个值)参数就是 void*
指针运算
指针运算是一种"弊大于利"的操作.
指针运算很容易产生"野指针".
指针 +- 整数 ; 指针 - 指针 ; 指针的关系运算.
指针 + 整数 VS 整数 + 整数
#include <stdio.h>
#include <stdlib.h>
int main(){
char* p = (char*)0x100;
printf("%p\n",p + 1);
system("pause");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main(){
int* p = (int*)0x100;
printf("%p\n",p + 1);
system("pause");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main(){
double* p = (double*)0x100;
printf("%p\n",p + 1);
system("pause");
return 0;
}
指针 + 1 相当于地址向后跳过一个元素.
指针 - 1 相当于地址向前跳过一个元素.
#include <stdio.h>
#include <stdlib.h>
int main(){
int arr[4] = { 1, 2, 3, 4 };
int* p = &arr[0];
printf("%p\n",arr); 可能会疑惑,数组arr可以直接用%p打印吗?
又要提到那个惊天bug!
1.数组在作为函数参数的时候会隐式转成指针
2.数组名直接printf打印也会隐式转成指针
3.数组名参与算术运算也会隐式转成指针
printf("%p\n",p);
printf("%p\n",p + 1);
system("pause");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main(){
int arr[4] = { 1, 2, 3, 4 };
int* p = &arr[0];
printf("%d\n",arr[1]);
printf("%d\n",*(p + 1)); //这是解引用
printf("%d\n",p[1]); //p是一个指针,它可以[]取下标
system("pause");
return 0;
}
*(p + 1) 和 p[1] 是等价的;可以理解成p[1] 是 *(p + 1)简化写法.但是这样的语法设定相当糟糕.
数组很多时候就隐式转成指针了.指针有时候还能像数组一样来使用(方括号取下标操作)
这俩概念相似,一定要做好区分.
数组取下标能不能填负数?不能
指针取下标能不能填负数?可以(只要它运算之后是有效内存)
#include <stdio.h>
#include <stdlib.h>
int main(){
int arr[4] = { 1, 2, 3, 4 };
int* p = &arr[1];
printf("%d\n",*(p - 1));
printf("%d\n",p[-1]);
system("pause");
return 0;
}
指针 - 指针(只能减不能加嗷)
#include <stdio.h>
#include <stdlib.h>
int main(){
int arr[4] = { 1, 2, 3, 4 };
int* p1 = &arr[0];
int* p2 = &arr[2];
int ret = p2 - p1;
printf("%p %p\n", p1, p2);
printf("ret = %d\n",ret);
system("pause");
return 0;
}
指针相减本质上就是在算两个指针之间隔了几个元素(和指针类型相关).
指针相减其实算是指针 +- 整数的逆运算.
p2 - p1 => 2;p1 + 2 => p2
指针相减大部分情况下虽然语法允许,但是是没有意义的.
指针相减要想有意义,必须满足两个条件:
1.两个指针的类型相同.
2.两个指针必须要指向同一个连续的内存空间.
因为 void* 未知大小,所以不能进行+-整数的运算,也不能进行指针相减.
指针的关系运算
针对比较相等,这个还好. 规则就是比较两个指针中存的地址是不是一样的.
==
!=
针对比较大小,这个一般也是没有意义的.比较地址数值的大小.
一般是不需要用的.如果非要用的话,也要保证两个前提.
1.两个指针类型相同
2.两个指针指向同一个连续的内存空间(数组,malloc)
<
<=
>
>=
比较两个字符串可以使用 "=="来直接比较吗?
#include <stdio.h>
#include <stdlib.h>
int main(){
char str1[] = "hehe";
char str2[] = "hehe";
printf("%p %p\n",str1,str2);
if (str1 == str2){
printf("1\n");
}
else{
printf("2\n");
}
system("pause");
return 0;
}
我们发现它的输出结果并不相等.因为它是两个数组的地址在进行比较.
如果想要比较两个字符串的内容相等与否需要引入string.h头文件中的cmp.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char str1[] = "hehe";
char str2[] = "hehe";
printf("%p %p\n",str1,str2);
//str => string ; cmp => compare
if (strcmp(str1,str2) == 0){
printf("相等\n");
}
else{
printf("不相等\n");
}
system("pause");
return 0;
}
C语言中,比较两个字符串,有两种方式:
1. == 比较字符串的身份/地址(是不是同一个字符串变量)
2.strcmp 比较字符串的内容(字符串里面每个字符是不是依次相同)
strcmp 除了能比较字符串相等之外,还能比较字符串的大小.
字符串大小的比较规则:先看第一个字符的ASCII值的大小.如果能分出大小,结果就确定了,如果第一个字符相同,再依次比较下一个字符的ASCII.字典序
strcmp(str1,str2)
如果str1 小于 str2 返回一个 < 0 的整数(不是-1)
如果str1 大于 str2 返回一个 > 0 的整数(不是+1)
换一种写法:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char* str1 = "hehe";
char* str2 = "hehe";
printf("%p %p\n",str1,str2);
if (str1 == str2){
printf("相等\n");
}
else{
printf("不相等\n");
}
system("pause");
return 0;
}
结果会怎么样?
虽然这样比较的依然是字符串的地址,但这两个共用同一个创建的字符串常量.
二级指针
二维数组:本质上也是一个二维数组,只不过里面的元素也是一个一维数组.
二级指针:本质上也是一个一级指针,只不过这个指针指向的内容还是一个一级指针.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int* IntPtr;
int main(){
int num = 10;
IntPtr p = #
//二级指针
IntPtr* pp = &p;
//*pp和p是等价的
//*p和num是等价的
//**pp就和num是等价的
printf("%d\n",**pp);
system("pause");
return 0;
}
指针数组
指针数组:是一个数组,数组中的每一个元素是一个指针.
数组指针:是一个指针
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
//指针数组
int* arr[4] = { 0 };
//数组指针
int(*arr)[4] = NULL;
//数组的类型如何理解
//变量名叫 a,a 的类型叫做 int[4]
//b 的类型 int[5]
//a 的类型和 b 的是否相同? 不相同
int a[4];
int b[5];
system("pause");
return 0;
}
指针数组非常有用.以后会经常用到.数组指针没什么用,用处就是用来做指针数组的区分.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
int arr[4] = { 0, 1, 2, 3 };
int(*p)[4] = &arr;
//int*
printf("%p\n",&arr[0]);
//int*
printf("%p\n", arr);
//int(*arr)[4]
printf("%p\n", &arr);
system("pause");
return 0;
}
const 和指针搭配的时候,有说法.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
int num = 10;
int num2 = 20;
const int* p = #
//第一种操作,根据地址修改对应的变量
//*p = 100;
//第二种操作,修改指针的指向
//p = &num2;
system("pause");
return 0;
}
const int* p 限制根据指针修改对应的内存
int const* p 限制根据指针修改对应的内存
int* const p 限制修改指针的指向