初始C语言中的指针(翁凯男神MOOC)
运算符 &
● scanf("%d",&i);
●获得变量的地址,它的操作数必须是变量
● int i; printf("%x",&i);
Int i=;
printf("%p\n",&i);
● 地址的大小是否与int相同取决于编译器
&不能取的地址
●&不能对没有地址的东西取地址
●&(a+b)
●&(a++)
●&(++a)


int a[];
printf("%p\n",&a);
printf("%p\n",a);
printd("%p\n",&a[]);
指针
●就是保存地址的变量
int i;
int *p=&i;
●指针指向某一个变量,指针里存放那个变量的地址
指针变量
●变量的值是内存的值
●普通变量的值是实际的值
●指针变量的值具有实际值的变量的地址
作为参数的指针
● void f(int *p);
●在被调用的时候得到了某个变量的地址;
●int i=0;f(&i);
●在函数里面可以通过这个指针访问外面的这个i
访问那个地址上的变量*
● *是一个单目运算符,用来访问指针的值所表示的地址上的变量
● 可以做右值也可以做左值
● int k=*p;
● *p = k+1;
指针应用场景
●交换两个变量的值
void swap(int *pa.int*pb)
{
int t = *pa;
*pa=*pb;
*pb=t;
}
●函数返回多个值,某些值就只能通过指针返回
void minmax(int a[],int len,int *max,int *min); int main(int argc, char **argv)
{
int a[]={,,,,};
int min,max;
minmax(a,sizeof(a)/sizeof(a[]),&min,&max);
printf("min=%d,max=%d\n",min,max); return ;
}
void minmax(int a[],int len, int *max,int *min){
int i;
*min=*max=a[];
for(i=;i<len;i++){
if(a[i]<*min){
*min=a[i];
}
if(a[i]>*max){
*max=a[i];
}
}
}
●函数返回运算的状态,结果通过指针返回
●常用的套路是让函数返回特殊的不属于有效范围内的值来表示出错:
● -1 或 0 (在文件操作会看到大量的例子)
●但是当任何数值都是有效的可能结果时,就得分开返回了
int divide(int a,int b ,int *result); int main(int argc, char **argv)
{
int a=;
int b=;
int c;
if(divide(a,b,&c)){
printf("%d\n%d\n%d\n",a,b,c);
} return ;
}
int divide(int a,int b,int *result)
{
int ret=;
if(b==)ret=;
else{
*result=a/b;
}
return ret;
}
●后续的语言(C++ Java)采用了异常机制来解决这个问题
指针最常见的错误
●定义了指针变量,还没有指向任何变量,就开始使用指针
传入函数的数组成了什么?
●函数参数表中的数组实际上是指针
●size of (a)==size of (int*)
●但是可以用 数组的运算符[]进行运算
数组参数
●以下四种函数原型是等价的
● int sum(int *ar,int n);
●int sum (int *,int);
●int sum (int ar[],int n);
●int sum (int [],int);
数组变量本身就是特殊的指针
●数组变量本身表达地址,所以
● int a[10]; int*p=a; //无需用&取地址
●但是数组的单元表达的是变量,需要用&取地址
●a == &a[0]
●[] 运算符可以对数组做,也可以对指针做
●p[0] <==> a[0]
● *运算符可以对指针做,也可以对数组做
● *a=25;
● 数组变量是const的指针,所以不能被赋值
● int a[] <==> int *const a =
指针与const
指针是const(指针指向那个变量,这个事实不能被改变)
●表示一旦得到了某个变量的地址,不能再指向其他变量
int *const q =&i; // q是const
*q = ; // OK
q++; //ERROR
所指的是const
●表示不能通过这个指针去修改那个变量(并不能使得那个变量成为const)
const int *p = &i;
*p=; // ERROR! (*p)是const
i=; // OK
p=&j; //OK
转换
●总是可以把一个非const的值转换成const的
void f(const int *x);
int a = ;
f(&a); //OK
const int b=a;
f(&b); //OK
b = a+1; //ERROR
●当要传递的参数的类型比地址大的时候,这是常用的手段:既要用比较少的字节数传递给参数,又能避免函数对外面的变量的修改
const数组
const int a[]={,,,,};
●数组变量已经是const的指针了,这里的const表明数组的每个单元都是const int
●所以必须通过初始化进行赋值
指针运算
●给一个指针加1表示要让指针指向下一个变量
int a[];
int *p=a;
*(p+1)--->a[1]
●如果指针不是指向一片连续分配的空间,如数组,则这种运算没有意义
指针计算
●给指针加,减一个整数(+,+=,-,-=)
●递增递减(++/--)
●两个指针相减(地址的差除以sizeof( 类型))
*p++
●取出p所指的那个数据来,完事之后顺便把p移动到下一个位置去
● *的优先级虽然高,但是没有++高
●常用于数组类的连续空间操作
●在某些CPU上,这可以直接被翻译成一条汇编指令
char ac[] = {,,,,,,-}; // -1不是有效数字
char *p=ac
while(*p != -){
printf("%d\n",*p++);
}
遍历数组ac
0地址
●当然你的内存中有0地址,但是0地址通常是个不能随便碰的地址
●所以你的指针不应该具有0值
●因此可以用0地址来表示特殊的事情:
●返回的指针是无效的
●指针没有被真正初始化(先初始化为0)
●NULL是一个预定定义的符号,表示0地址
●有的编译器不愿意你用0来表示0地址
指针的类型
●无论指向什么类型,所有的指针的大小都是一样的,因为都是地址
●但是指向不同类型的指针是不能直接互相赋值的
●这是为了避免用错指针
指针的类型转换
●void* 表示不知道指向什么东西的指针
●指针类型亦可以转换类型
●int *p = &i; void*q = (void*)p;
●这并没有改变p所指的变量的类型,而是让后人用不同的眼光通过p看它所指的变量
●我不再当你是int啦,我认为你就是一个void!
用指针来做什么
●需要传入较大的数据时用作参数
●传入数组后对数组做操作
●函数返回不止一个结果
●需要用函数修改不止一个变量
●动态申请内存时
malloc
●#include<stdlib.h>
●向malloc申请的空间的大小都是以字节为单位的
●返回的结果是void*,需要类型为自己需要的类型
●(int*)malloc(n*sizeof(int))
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int number;
int *a;
printf("输入数量");
scanf("%d",&number);
a=(int*)malloc(number*sizeof(int));
for (i=;i<number;i++){
a[i]=i*i;
}
free(a);
return 0;
}
没空间了?
●如果申请失败则返回0,或者叫做NULL
void *p=0;
int cnt=;
while((p=malloc(**))){
cnt++;
free(p)
printf("分配了%d00MB的空间\n",cnt);
free()
●把申请得来的空间还给系统
●申请过来的空间,最终都要还
●混出来的,迟早都要还的
●只能还申请的空间的首地址
初始C语言中的指针(翁凯男神MOOC)的更多相关文章
- 判断素数(翁凯男神MOOC)
从2到x-1测试是否可以整除 int isPrime(int x); int main(int argc, char **argv) { int x; scanf("%d",&am ...
- C语言中的指针数组
C语言中的指针数组是什么,像 char *a[]={"ddd","dsidd","lll"}; 这里讲一下注意如果我们使用了a也就是首元素的 ...
- 【ZZ】C 语言中的指针和内存泄漏 & 编写高效的C程序与C代码优化
C 语言中的指针和内存泄漏 http://www.ibm.com/developerworks/cn/aix/library/au-toughgame/ 本文讨论了几种在使用动态内存分配时可以避免的陷 ...
- GO语言中的指针
http://www.tizgrape.com/?p=100 Go语言中的指针语法和C++一脉相承,都是用*作为符号,虽然语法上接近,但是实际差异不小. Go使用var定义变量: var v6 *in ...
- C语言中的指针笔记
C语言指针 得到变量的地址 可以使用&运算符找到变量保存在内存中的位置 int x = 1; printf("x的内存地址是"%p\n",&x) %p格式 ...
- C语言中的指针加减偏移量
C语言指针偏移技巧(也是一个要注意的坑) - 陈杰柱的博客 - CSDN博客 https://blog.csdn.net/cjzjolly/article/details/82116772 C语言中 ...
- C 语言中的指针和内存泄漏
引言对于任何使用 C 语言的人,如果问他们 C 语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏.这些的确是消耗了开发人员大多数调试时间的事项.指针和内存泄漏对某些开发人员来说似乎令人畏惧 ...
- C语言中的指针和内存泄漏
引言 对于任何使用C语言的人,如果问他们C语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏.这些的确是消耗了开发人员大多数调试时间的事项.指针和内存泄漏对某些开发人员来说似乎令人畏惧,但是 ...
- C语言中的指针学习(小黑板)
指针是C语言中的精华所在,也是C语言的危险之在,今天又重现温习了一下C语言,做了一下总结. 欢迎批阅. (1)指针的含义指针的本质也是数据类型,它是指向地址的变量.例如: { int a = 10; ...
随机推荐
- Linux性能优化 第四章 性能工具:特定进程CPU
4.1进程性能统计信息 4.1.1. 内核时间VS用户时间 一个应用程序所耗时间最基本的划分是内核时间与用户时间.内核时间是消耗在Linux内核上的时间,而用户时间则是消耗在应用程序或库代码上的时间. ...
- day16(软件开发目录规范)
模块的使用01 模块的循环导入问题 解决方案一: 把循环导入的语句放到名字定义的后面 解决方案二: 将循环导入语句放到函数内(先定义确定名称空间)02 区分python文件的两种用途 #当文件被执行时 ...
- c# 枚举的定义,枚举的用法,获取枚举值
1.定义枚举类型 public enum Test { 男 = , 女 = } 2.获取枚举值 public void EnumsAction() { var s = Test.男;//男 var a ...
- Python笔记:用for循环删除列表中的元素
for运行过程中会有一个指针来记录当前循环的元素是哪一个,一开始这个指针指向第0个元素,然后获取它,接着删除第0个元素,这时候,原来是第1个的元素会变成第0个,当指针向后移动一次,指向了现在第1个元素 ...
- [Unity插件]Lua行为树(十三):装饰节点完善
之前介绍了组合节点中三大常用的节点:BTSequence.BTSelector和BTParallel,一般来说,这三种就够用了,可以满足很多的需求. 接下来可以完善一下装饰节点,增加几种新的节点. 1 ...
- 项目经验分享[转自min.jiang]
最近三个月,我非常荣幸的做为TeamLeader带领几个小组成员做了一个国外项目,这里想为大家分享一些小经验,尽管我佣有六年多的项目经验,但我一直的方向是架构师.大家知道架构师一般情况是偏向技 ...
- Mac技巧之苹果电脑Mac OS X系统自带的鼠标所在点颜色RGB值查看工具:数码测色计
转自http://www.mac52ipod.cn/post/show-mouse-point-rgb-color-by-apple-mac-os-x-tool.php
- uva-11054-模拟
题意:一条街有许多卖酒的店,有些店需要进酒,有些店需要出酒,所有的店的需求总和为0,问怎么移动,使酒的移动总和最少. 模拟,考虑一家店的需求为xi,无论是从左或者是从右或者其他形式,让xi->0 ...
- 销售人员的分析,也可以用类似RFM的思路吗?
本文转自知乎 作者:接地气的陈老师 ————————————————————————————————————————————————————— 有同学问:“销售人员的分析,也可以用类似RFM的思路吗, ...
- Android 关于缓存的一些类
在做项目的时候,难免需要将一些数据存储在手机中,之前用sqlite和sharepreference,但是使用起来不是很方便.最近用到了一些缓存的类,非常方便,特此记录下来. ASimpleCache ...