以32为系统为例。

1、指针与地址
指针是一种变量,保存了所指向对象的地址。
1.1 定义
int i = 10;
int *p = &i; //定义了一个指针p,它指向一个int型的变量
&是地址运算符,*是间接引用运算符。
&i是取i在内存中的地址,*p = &i是将i的地址赋值给p,即p的值是i的地址。
1.2 引用
*p = 100 等价于 i = 100,即将i的值改成100
*p += 1 等价于 i += 1,即将i的值加1
*p++改变了p所指向的地址,此时p不再指向i的地址,而是指向i的地址+4的新地址。因为*(间接引用运算符)和++具有相同的优先级,且是从右到左的结合性,所以等价于*(p++)。p++是将指针加1,指向内存中下一个地址。由于这里的p是int型的,实际上是偏移了sizeof(int)=4个字节。例:
int i = 10;
int *p = &i;
*p++;
printf("i=%d, &i=%p, p=%p\n", i, &i, p);
打印结果:i=10, &i=0xbf99bd78, p=0xbf99bd7c
注意:绝对不能这么写*p++ = 111,因为这无意中非法改变了p下一个内存地址的值。

++*p 等价于 i的值加1
*++p 等价于 *p++
*p + 1 等价于 i 的值 加1
*(p + 1) 等价于*p++

2、指针和数组
int a[10];
int *p = &a[0]; //指针p指向数组a的首地址元素a[0]
或者int *p = a; //数组名所代表的就是该数组的第一个元素的地址,直接赋值给p

引用第i个元素:
a[i] 或者 *(a+i) 或者 *(p+i) 或者 p[i]

数组名和指针的差别:
指针是一个变量,可以赋值或者++,如p=a,p++
但数组名不行,不能这样:a=p, a++

指针的运算包括:
相同类型指针之间的赋值运算;指针同整数之间的加减法运算;指向相同数组中元素的两个指针的减法或比较运算;指针赋值为0,或指针与0之间的比较运算。

3、指针数组和指向指针的指针
指针数组:int *p[10]; //p是一个指针数组,具有10个元素,每个元素都是一个指向int型对象的指针。
指向指针的指针: int **p; //p是一个指针,指向一个int *型对象

4、二维数组
int a[10][20]; //二维数组,有10行,每行20列
int a[][20] = {........}; //二维数组,每行20列,行数会根据{...}内的值的个数自动计算,行数={...}中值的个数/20 + 1
二维数组必须要指定列数,行数可以不用指定。

二维数组作函数参数时,函数的声明方式可以是:
f (int a[10][20]) {...} 或者
f (int a[][20]) {...} 或者
f (int (*a)[20]) {...}
不能是f (int *a[20]) {...}

数组指针(行指针):char (*p)[20]是一个指针,指向具有20个char型元素的一维数组。
sizeof(p)=4,占用一个指针的存储空间
char a[10][20];
char (*p)[20];
p=a; //二维数组首地址给p,p指向a[0][0],即第0行的第0个元素
p++; //执行后,p指向a[1][0],即第1行的第0个元素
指针数组:char *p[20]是一个数组,具有20个元素,每个元素都是一个指向char型对象的指针
sizeof(p)=80,占用20个指针的存储空间
char a[10][20];
char *p[20];
p[0]=a[0]; //p[0]指向二维数组a的第0行
p[1]=a[2]; //p[1]指向二维数组a的第2行
两者的引用方式一样,都是:*(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]
原因:[]的优先级高于*的优先级。

5、指向函数的指针
int (*f)(int i, int j) 定义了一个函数指针,这个函数有两个参数i和j,函数返回一个int型对象。
圆括号是必须的,否则就变成了int *f(int i, int j),这表示函数f返回一个int *型对象。

6、总结

char **x:x是指向指针的指针
char (*x)[10]:x是一个数组指针,指向一个具有10个元素的数组
char *x[10]:x是一个指针数组,每个元素都是一个指向char型对象的指针
char *x( ):x是一个函数,该函数返回一个指向char型对象的指针
char (*x)( ):x是一个函数指针,该函数返回一个char型对象
char (*(*x( ))[10 ])( ):定义了一个函数,该函数返回一个具有10个元素的数组指针,元素类型是函数x返回的指向char类型对象的指针
char (*(*x[10])())[2]:定义了一个数组,数组有两个元素,每个元素的类型是函数返回的指向一个10个元素的指针数组的指针

C语言之指针的更多相关文章

  1. 浅谈c语言的指针

    对于非计算机专业的同学,c语言的指针往往就是老师的一句“指针不考“就带过了.c语言的指针号称是c语言的灵魂,是c语言中最精妙的部分. 指针本质上也是变量,也就是一段内存,只是他的特殊之处是他存储的数据 ...

  2. C#委托与C语言函数指针及函数指针数组

    C#委托与C语言函数指针及函数指针数组 在使用C#时总会为委托而感到疑惑,但现在总新温习了一遍C语言后,才真正理解的委托. 其实委托就类似于C/C++里的函数指针,在函数传参时传递的是函数指针,在调用 ...

  3. C语言二重指针与malloc

    (内容主要源于网上,只是加入了些自己的剖析) 假设有一个二重指针: char **p; 同时有一个指针数组 char *name[4]; 如何引用p呢? 首先我们有程序代码如下 #include &l ...

  4. C语言函数指针基础

    本文写的非常详细,因为我想为初学者建立一个意识模型,来帮助他们理解函数指针的语法和基础.如果你不讨厌事无巨细,请尽情阅读吧. 函数指针虽然在语法上让人有些迷惑,但不失为一种有趣而强大的工具.本文将从C ...

  5. 为什么C/C++语言使用指针

    这是参加面试时,面试官问的一道开放性题目. 问题是:为什么C/C++语言使用指针? 这个问题一问出来,直接被面试官秒杀了,面试官大神,你怎么不按套路出牌啊? 说好的malloc和new的区别呢?说好的 ...

  6. C语言的指针变量

    C语言的指针变量 在C语言中,变量是固定范围的存储空间,它存储的是赋给他的值, 比如: ; /* 这里是定义一个整型变量a,并把12这个值存储在a的地址空间上 这个地址空间是系统随机分配的,对用户是透 ...

  7. Android For JNI(五)——C语言多级指针,结构体,联合体,枚举,自定义类型

    Android For JNI(五)--C语言多级指针,结构体,联合体,枚举,自定义类型 我们的C已经渐渐的步入正轨了,基础过去之后,就是我们的NDK和JNI实战了 一.多级指针 指针的概念我们在前面 ...

  8. “对外部(局部)变量的访问”是C语言函数指针的最大弱点

    1.“对外部(局部)变量的访问”是C语言函数指针的最大弱点 . #include <stdio.h> #include <stdlib.h> /* 结构体定义 */ struc ...

  9. go语言学习--指针的理解

    Go 的原生数据类型可以分为基本类型和高级类型,基本类型主要包含 string, bool, int 及 float 系列,高级类型包含 struct,array/slice,map,chan, fu ...

  10. C语言中指针占据内存空间问题

    以前一直有个疑问,指向不同类型的指针到底占用的内存空间是多大呢? 这个问题我多次问过老师,老师的答案是"指向不同类型的指针占据的内存空间大小不同",我一直很之一这个答案,今天我就做 ...

随机推荐

  1. C#_delegate - example

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Dele ...

  2. 【转】cocos2d-x 2.0版本 自适应屏幕分辨率

    http://codingnow.cn/cocos2d-x/975.html 我使用的版本是cocos2d-2.0-x-2.0.4,cocos2dx-2.0版本对多分辨率适配提供了很好的支持,使用起来 ...

  3. PHP获取远程图片并调整图像大小

    <?php /** * *函数:调整图片尺寸或生成缩略图 *修改:2013-2-15 *返回:True/False *参数: *   $Image   需要调整的图片(含路径) *   $Dw= ...

  4. javascript笔记02:严格模式的特定要求

    1.严格模式变量必须声明,不然会报错: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &quo ...

  5. uiautomator做自动化的过程

    UIautiomator官网地址:http://android.toolib.net/sdk/index.html 1.环境搭建 使用uiautomator需要导入jar包,uiautomator.j ...

  6. 类型转换(CCstring int string char UTF-8互转)

    在做数据转换时,最好包含以下头文件 #include <iostream> #include <cmath> #include <string> #include  ...

  7. dagger和butterknife使用冲突

    两者会冲突的主要原因是因为两者都有:javax.annotation.processing.Processor 于是在build.gradle中添加如下配置即可: // 注释冲突 packagingO ...

  8. Android更改桌面应用程序launcher的两种方式

    http://blog.csdn.net/mdx20072419/article/details/9632779/ launcher,也就是android的桌面应用程序.下图是我正在使用的魅族手机的l ...

  9. 全局负载均衡GSLB之“部署篇”

    http://virtualadc.blog.51cto.com/3027116/875622 前言 随着web应用的不断发展,客户对于业务的稳定性.可靠性等也提出更高的要求,已不再局限于IDC内部的 ...

  10. ubuntu系统下wireshark普通用户抓包设置

    dumpcap需要root权限才能使用的,以普通用户打开Wireshark,Wireshark当然没有权限使用dumpcap进行截取封包.   虽然可以使用    sudo wireshark    ...