C语言指针收藏
指针是什么
》》每一个内存单元只能同时存储一个数据,如何保证内存单元同时只能存储一个数据,可以使用编号的方式实现内存单元标记,此编号就是指针。
》》指针是一个变量,指针是存放着一个数据的内存地址而不是数据本身的值,其是查找数据的另一种方式
相关运算符
【&】在变量中取地址
【*】在地址中取变量
测试小程序:
- #include<stdio.h>
- void main() {
- int i = ;//定义一个变量,并赋初始值为10
- int *p = &i;//定义一个指针变量,并赋初始值为i的地址
- *p = ;
- printf("%d=%d", *p,i);//输出199=199
- printf("---%d---", p);//得到变量i的地址
- }
指针变量的类型
》》指针类型:int *、float*、long*、double*、char*等等
》》指针变量的类型需要与存储的数据类型相同
》》确定类型可以方便指针变量确定存储数据的大小,为数据寻找到结束符,如int类型占四个字节、char占一个字节。也方便指针使用加1或减1操作,如int加减1会跳动4个字节,char加减1会跳动两个字节。
指针的赋值
int i=10; int *p=&i;
int *pp;
pp=p;
指针运算符:
*p++
等同于*(p++),运算优先级为从右到左,应该是先*p取值,然后地址移动一位,要区别与*(++p)。
- char *ch="";
- //printf("%c\r\n",*ch++);//输出0
- //printf("%c\r\n",*(ch++));//输出0
- printf("%c\r\n",*(++ch));//输出1
指针变量作为函数参数
- #include<stdio.h>
- //int *a1=&b1;
- void fun(int *a1, int* a2) {
- *a1 = ;
- int ii = ;
- a2 = ⅈ//让指针重新指向另外一个地址
- printf("得到的数据:%d,%d", *a1, *a2);//输出100,99
- }
- void main() {
- int b1 = , b2 = ;
- fun(&b1, &b2);
- printf("调用函数后:%d,%d", b1, b2);//输出100,2
- }
输出b2的结果并不是相同的值,是因为执行调用函数改变了实参指针变量的值,并不是改变了实参指针变量所指变量的值
数组作为函数参数
- #include<stdio.h>
- void fun1(int *arr){
- arr[]=;
- arr[]=;
- }
- void fun2(int arr[]){
- arr[]=;
- arr[]=;
- }
- void main(){
- //变量初始化
- int i;
- int a[]={,,,,,,};
- //函数调用
- fun1(a);
- fun2(a);
- //打印
- for(i=;i<sizeof(a)/sizeof(int);i++){
- printf("%d ",a[i]); //10 11 100 110 4 5 6
- }
- }
数组作为函数参数会自动退化为指针
函数形参如果是数组,不管下标是多少都会自动转换为数组的首地址指针
- #include<stdio.h>
- void fun1(int *p){
- printf("%d",p[]);//
- }
- void fun2(int p[]){
- printf("%d",p[]);//
- }
- void fun3(int p[]){
- printf("%d",p[]);//
- }
- void fun4(char *p[]){
- printf("%s",p[]);//dong
- }
- void fun5(char **p){
- printf("%s",p[]);//dong
- }
- void main(){
- int ii[]={,,};
- fun1(ii);
- fun2(ii);
- fun3(ii);
- char *ch[]={"dong","xiao"};
- fun4(ch);
- fun5(ch);
- }
一维数组指针变量
数组名(如arr)代表元素的首地址,数组第一个元素的地址也是这个数组的首地址(如&arr[0])。
数组指针中使用加减1将跳到下一个或者上一个数组元素地址,与使用 &arr[n+1] 基本相同。
如果整数数组名为arr,运行int *p=arr,则*(p+3)、p[3]、*(arr+3)、arr[3]效果均是取出数组arr的第三个元素,在编译时arr[3]实际上是*(arr+3)处理的。
- #include<stdio.h>
- void main() {
- int arr[] = { ,,,, };
- int *p = arr;
- int *pp = &arr[];
- printf("%d", *(p+));//输出2
- }
函数数组参数
- #include<stdio.h>
- //等价于void fun(char a1[]) {
- void fun(char *a1) {
- *(a1 + ) = 'c';//改变第二个值的内容
- }
- void main() {
- char b1[] = { "" };
- fun(b1);
- printf("调用函数后:%s", b1);//输出: 12c456789
- }
二维数组指针变量
- #include<stdio.h>
- void main() {
- int a1[][] = { {,,},{,,} };
- int a[][] = { ,,,,, };
- printf("地址:%d==%d==%d==%d", a[], &a[][],*(a+),a+);//输出地址
- printf("%d===%d==%d", a[][], *(*(a + )+),*(a[]+));//得到值
- }
指针引用字符串
字符串常量【char *ch = "dong xiao dong";】表示其指向地址的内容不可变,但指向的地址是可变的;
字符串变量【char ch[] = "dong xiao dong";】其指向地址的内容可变。
- #include<stdio.h>
- void main() {
- //char *ch = "dong xiao dong"; //字符串常量,不可变
- char ch[] = "dong xiao dong"; //字符数组,可变
- ch[] = '';//字符串常量运行这条将报错
- printf("%s\n", ch);
- }
可变格式的输出函数:
- #include<stdio.h>
- void main() {
- char *ch = "dong xiao %d\n";
- printf(ch, );
- ch = "xiaoxiao%d\n";
- printf(ch, );
- char chh[] = "dongdong %d\n";
- printf(ch, );
- }
指向函数的指针
【int(*p)(int, int);//定义一个函数指针变量p】,第一个int表示返回值类型,第二个int和第三个int表示函数的参数类型。注意*p两侧的括号不能省略,表示p先与*结合,是指针变量,然后再于后面的()结合,()表示是函数,即该指针变量不是指向一般的变量,而是指向函数。如果写成“int * p(int,int);”,由于()优先级高于*,它相当于“int *(p(int,int))”,就成了声明一个p函数,并且这个函数的返回值是指向整型变量的指针。
返回值为int
- #include<stdio.h>
- void main() {
- int minto(int a, int b);//函数声明
- int(*p)(int, int);//定义一个函数指针变量p
- p = minto;//函数指针指向函数minto首地址
- int cc = (*p)(, );//调用函数
- printf("Min===%d", cc);
- }
- int minto(int a, int b) {
- if(a > b) return b;
- else return a;
- }
无返回值:
- #include<stdio.h>
- void main() {
- void fun(int a);//函数声明
- void (*p)(int);//定义一个函数指针变量p
- p = fun;//函数指针指向函数fun首地址
- (*p)();//调用函数
- }
- void fun(int a) {
- printf("%d\n", a);
- }
指向函数指针作为函数的参数
- #include<stdio.h>
- void main() {
- int fun(int(*addpp)(int, int), int x, int y);//函数声明
- int add(int i, int j);
- int ii=fun(add, , );//传递函数名和参数即可
- printf("输出相加的值为:%d", ii);
- }
- //int (*addpp)(int,int);addpp=add;
- int fun(int (*addpp)(int,int),int x,int y){
- int cc = (*addpp)(x, y);
- return cc;
- }
- int add(int i, int j) {
- return i + j;
- }
返回指针的函数
- #include<stdio.h>
- void main() {
- int* add(int i, int j);
- int *p = add(, );
- printf("输出相加的值为:%d", *p);
- }
- int* add(int i, int j) {
- int aa = i + j;
- return &aa;//返回地址
- }
指针数组
一个数组其全部元素都存放着指针,就是指针数组【int * p[5];】
- #include<stdio.h>
- void main() {
- //指针数组
- char * p[] = { "dong1","xiao2","dong3","dong4" };
- printf("%s\n", p[]);
- }
进阶版
- #include<stdio.h>
- void main() {
- //指针数组(字符串)
- char * p[] = { "dong1","xiao2","dong3","dong4" };
- char **pp;
- pp = p;
- printf("%s\n", *(pp+));//转换一次就可以拿到对应字符串的首地址通过%s打印
- //指针数组(整数)
- int a[]= {,,, };
- int * ip[] = { &a[],&a[],&a[],&a[],&a[]};
- int **ppp = ip;
- printf("%d\n", *(*ppp+));//转换第一次得到存储的指针,再次转换得到值
- }
void类型指针
- void a;//定义一个无类型变量,错误,不能确定分配的内存大小
- void *a;//定义一个无类型指针,可行,指针类型都是4个字节(32位,64位为8个字节)
void *p;表示指针变量p不指向一个确定的类型数据,它的作用仅仅是用来存放一个地址。
可以将任意类型的指针直接给void指针赋值,但是如果需要将void指针的赋值给其他类型的指针,则需要进行强制类型转换
- #include<stdio.h>
- void fun1(void *i){
- int *p=(int *)i;//强制类型转换
- *p=;
- }
- void main(){
- int ii=;
- fun1(&ii);
- printf("%d",ii);//输出100
- }
错误示范
1、
int *p=10; //等同于:int *p; p=10;
分析:非法操作,内存地址不能用户自定义。10相当于一个内存地址,该内存地址的值不确定且也不明确该地址是否可以直接访问,正确的应该是使用【&变量名】得到内存地址。
2、
- int f = 12.3;
- int *p;
- *p = &f; //错误1
- int ff = &f; //错误2
分析:指针(地址)必须赋值给指针变量
C语言指针收藏的更多相关文章
- C语言指针转换为intptr_t类型
1.前言 今天在看代码时,发现将之一个指针赋值给一个intptr_t类型的变量.由于之前没有见过intptr_t这样数据类型,凭感觉认为intptr_t是int类型的指针.感觉很奇怪,为何要将一个指针 ...
- [转]C语言指针学习经验总结浅谈
指针是C语言的难点和重点,但指针也是C语言的灵魂 . 这篇C语言指针学习经验总结主要是我入职以来学习C指针过程中的点滴记录.文档里面就不重复书上说得很清楚的概念性东西,只把一些说得不清楚或理解起来比较 ...
- 不可或缺 Windows Native (7) - C 语言: 指针
[源码下载] 不可或缺 Windows Native (7) - C 语言: 指针 作者:webabcd 介绍不可或缺 Windows Native 之 C 语言 指针 示例cPointer.h #i ...
- C语言指针学习
C语言学过好久了,对于其中的指针却没有非常明确的认识,趁着有机会来好好学习一下,总结一下学过的知识,知识来自C语言指针详解一文 一:指针的概念 指针是一个特殊的变量,里面存储的数值是内存里的一个地址. ...
- (转载)c语言指针学习
前言 近期俄罗斯的陨石.四月的血月.五月北京的飞雪以及天朝各种血腥和混乱,给人一种不详的预感.佛祖说的末法时期,五浊恶世 ,十恶之世,人再无心法约束,道德沦丧,和现在正好吻合.尤其是在天朝,空气,水, ...
- 关于C语言指针的问题
在学习关于C语言指针的时候,发现这样一个问题,代码如下: #include<stdio.h> #include<stdlib.h> #include<string.h&g ...
- C语言指针类型 强制转换
关于C语言指针类型 强制转换 引用一篇文章: C语言中,任何一个变量都必须占有一个地址,而这个地址空间内的0-1代码就是这个变量的值.不同的数据类型占有的空间大小不一,但是他们都必须有个地址,而这个 ...
- C语言指针和数组知识总结(上)
C语言指针和数组知识总结(上) 一.指针的基础 1.C语言中,变量的值能够通过指针来改变,打印指针的语句符号可以是: %08x 2.指针的本质 指针的本质就是变量,那么既然是变量,那么一定会分配地址 ...
- C语言指针操作
欢迎访问我的新博客:http://www.milkcu.com/blog/ 原文地址:http://www.milkcu.com/blog/archives/pointer-manipulation. ...
随机推荐
- NULL、0、nullptr
C的NULL 在C语言中,我们使用NULL表示空指针,也就是我们可以写如下代码: int *i = NULL;foo_t *f = NULL; 实际上在C语言中,NULL通常被定义为如下: #defi ...
- CentOS7下安装pip和pip3
1.首先检查linux有没有安装python-pip包,直接执行 yum install python-pip 2.没有python-pip包就执行命令 yum -y install epel-rel ...
- javascript 函数,事件
1.函数字符串函数 var s=new string(); var ss="hello world"; var sss=""HELLO, WORLD" ...
- php学习笔记-获取表单数据
在网页上经常要填写用户名和密码,点击确认按纽之后,用户名和密码经过前端处理之后发送到了服务器上,那么服务器端怎么获取到这些用户提交的数据呢?就是通过超级全局变量 _POST和_GET 先拿_POST做 ...
- php学习笔记-默认参数
在定义函数的时候,我们可以把其中的一个参数变的特殊起来,使它有一个默认值,这个参数就叫默认参数.在调用这个函数的时候,你既可以给这个默认参数传递一个值,这样的话默认参数的值会被覆盖掉,也可以不给它传递 ...
- c++ 类中模版成员函数
C++函数模版与类模版. template <class T> void SwapFunction(T &first, T &second){ }//函数模版 templa ...
- spring第三篇
在昨天下午更新sprin第二篇中,叙述了将对象交给spring创建和管理,今天在spring第三篇中,主要写两个点一是spring的思想 二是spring中bean元素的属性配置. 1 spring思 ...
- 解决Spring MVC 对AOP不起作用的问题
用的是 SSM3的框架 Spring MVC 3.1 + Spring 3.1 + Mybatis3.1 第一种情况: Spring MVC 和 Spring 整合的时候,SpringMVC的spri ...
- c#委托与事件、消息、WndProc用法(转)
c#委托与事件 心得 c#用委托来实现事件通知机制.委托相当与c++函数指针.整个过程涉及一个呼叫者,一个被呼叫者,还有就是这个委托. - 实现步骤有以下几步: 1. 申明委托, 2.定义呼叫者和调用 ...
- 使用metasploit进行栈溢出攻击-3
有了shellcode,就可以进行攻击了,但是要有漏洞才行,真实世界中的漏洞很复杂,并且很难发现,因此我专门做一个漏洞来进行攻击. 具体来说就是做一个简单的tcp server,里面包含明显的栈溢出漏 ...