定义
指针0-255是系统保留的,不能读也不能写,NULL是指向0的
无论什么类型的指针,存的都是地址
内存地址都是无符号整形的,所以都是4个字节大小
10是四个字节int* 表示我如果要改的话,对应那边数据的四个字节char* 的话那就是对应那边数据的1个字节
指针里面只是地址,指针也是个变量
int main(int argc, char *argv[]){int a = 10;int b = 100;//指针是一种数据类型,p是指针类型变量用来指向一个变量的地址int * p = &a;p = &b;printf("%p\n", &b); //001CF878printf("%X\n", p); //1CF878//通过指针修改变量的值*p = 200;printf("%d\n", b); //200printf("%d\n", *p); //200//sizeof()指针类型在内存中的大小,所有指针在32位是4个字节大小//按照unsigned int为每一个内存分配编号 2的32次方-1 所以32位操作系统最多用4g内存, 64位显示是8printf("%d\n", sizeof(p)); //4printf("%d\n", sizeof(int *)); //4printf("%d\n", sizeof(char *)); //4system("pause");return EXIT_SUCCESS;}
万能指针指定类型
int main(int argc, char *argv[]){int a = 10;//指针里面存的是首地址void * p = &a;//转成指定类型,如果是char就转成char*(int *)p = 100;printf("%d\n", a); //100printf("%d\n", *(int *)p); //100system("pause");return EXIT_SUCCESS;}
如果是数组
int main(int argc, char *argv[]){int arr[10];//首地址void * p = arr;//改变首地址的值也就是arr[0]*(int *)p = 100;//改变arr[1],因为里面存的是int,每个元素占用4个字节,但是已经转为int了,int+1就过了4个字节*((int *)p + 1) = 200; //就是arr[1]for (int i = 0; i < 10; i++){printf("%d\n", arr[i]);}system("pause");return EXIT_SUCCESS;}
const
const修饰指针
const修饰变量是可以被修改的
int main(){//这种方式不安全,可以通过指针修改const int a = 10;printf("%d\n", a);int * p = &a;*p = 100;printf("%d\n", a);printf("%d\n", *p);getchar();return EXIT_SUCCESS;}
建议用define
#define LVL 100
const修饰指针类型
int main(){int a = 10;int b = 20;//如果const修饰int * 不能改变指针变量指向的内存地址的值//但是可以改变指针存的地址const int * p;p = &a;p = &b;printf("%d\n", *p);getchar();return EXIT_SUCCESS;}
const修饰指针变量
int main(){int a = 10;int b = 20;//const修饰指针变量int * const p = &a;//能改变指针变量指向地址的值,但不能改变指针指向的地址*p = 100;printf("%d\n", *p);getchar();return EXIT_SUCCESS;}
const同时修饰指针类型和指针变量
int main(){int a = 10;int b = 20;//const修饰指针类型并且指针变量,那么都不能改变const int * const p = &a;getchar();return EXIT_SUCCESS;}
const和非const类型转换
当一个指针变量 str1 被 const 限制时,并且类似const char *str1这种形式,说明指针指向的数据不能被修改;如果将 str1 赋值给另外一个未被 const 修饰的指针变量 str2,就有可能发生危险。因为通过 str1 不能修改数据,而赋值后通过 str2 能够修改数据了,意义发生了转变,所以编译器不提倡这种行为,会给出错误或警告。
也就是说,const char *和char *是不同的类型,不能将const char *类型的数据赋值给char *类型的变量。但反过来是可以的,编译器允许将char *类型的数据赋值给const char *类型的变量。
这种限制很容易理解,char *指向的数据有读取和写入权限,而const char *指向的数据只有读取权限,降低数据的权限不会带来任何问题,但提升数据的权限就有可能发生危险。
C语言标准库中很多函数的参数都被 const 限制了,但我们在以前的编码过程中并没有注意这个问题,经常将非 const 类型的数据传递给 const 类型的形参,这样做从未引发任何副作用,原因就是上面讲到的,将非 const 类型转换为 const 类型是允许的
指针和数组
指针遍历数组
int main()
{
//数组名是数组的首地址,这是个常量
int arr[10] = { 0 };
//指向数组的指针,当操作指针的时候,间接操作了数组
int* p = arr;
for (int i = 0; i < 10; ++i) {
// printf("%d\n", p[i]);
//这样也可以
printf("%d\n", *(p+i));
}
getchar();
return EXIT_SUCCESS;
}
指针操作数组
int main() {
//数组名是数组的首地址,这是个常量
int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
//指向数组的指针,当操作指针的时候,间接操作了数组
int *p = arr;
//指针操作数组
*p = 100;
*(p + 1) = 200;
p[5] = 300;
*(p + 3) = 700;
for (int i = 0; i < 10; ++i) {
// printf("%d\n", p[i]);
//这样也可以
printf("%d\n", *(p + i));
}
getchar();
return EXIT_SUCCESS;
}
多级指针
int main() {
int a = 10;
int* p = &a;
int** pp = &p;
int*** ppp = &pp;
//所以 ***ppp = a
getchar();
return EXIT_SUCCESS;
}
字符常量
int main() {
//字符数组,创建位置在栈区
char arr[] = "hello world";
//字符串常量,会在程序运行时,常量区,不能被修改的
// char * arr = "hello world";
printf("%p\n", arr);
printf("%s\n", arr);
getchar();
return EXIT_SUCCESS;
}
