C/C++关于指针

一些人可能为认为指针就是一个变量的内容就是加一个变量的地址. 这样认为非常对. 而如果说指针的知识只有这么多, 那么你就大错特错了. 指针并不是你想的那样只是一个变量指向另一个变量, 从而可以改变它的值.
我写这个的目的就是因为网络上有关于这些的好文章太少了. 虽然这篇文章是我自己的理解,
有可能会有一些许错误, 但是我感觉我还是有必要来分享我的理解的.
我的这篇文章主要是针对C语言的指针, 所以要学过指针. 明白什么是指针, 二级指针, 数组, 和多维数组与一维数组的关系, 因为下面我对这些知识就不再详细说明了.

操作方法

  • 01

    指针如果普通的理解就是一个变量(常变量)的内容就是另一个变量的地址. 32位编译器的指针类型其实就是unsigned int而64编译器就是unsigned long int.我在这里用的是VC2013.通过代码 cout<<sizeo(void*); 或printf("%p", sizeof(void*)); 我们知道了, 这个编译器的指针占4字节, 所以是32位编译器, 指针是unsigned int 类型的.

  • 02

    ‍int i = 10; int *p = &i; void *v = p;p = v;    //错误, 任何类型指针可以赋给void型指针, 但void型指针不能赋给其他任何指针.为什么要void型指针?自我感觉是为了完成一些库函数的任务比如说free的参数, malloc的返回值等等.*v;    错误, 因为它是void型指针, 编译器不知道sizeof(void)是多少. VC2013中的错误信息是: error C2100: 非法的间接寻址同样, v也不能作加减运算如:v += 1, 因为我们不知道void型的大小.

  • 03

    不在void型指针上作文章了, 现在开始说说指针的类型. 指针的类型并不是你想的一级指针, 二级指针等. 它其实是有 无数种类型的. 光是几级几级的指针就可以是无数种. 但还有别的. 指针共分为以下几种大类型: 1. 普通指针 typename *name(一级指针, 二级指针等) 2. 数组指针 typenamename [length](一维数组指针和以与变通指针通用) 3. 指向数组的指针 typename (*name )[length](就是在数组指针前面加个&, 它的值与不加&一样) 它们之间也是有关系的, 3归属于2, 2又归属于1. 为什么这样说?我们知道, 一个一维数组的数组名可以赋给一个指针, 如: int a[10]; int *p = a; 这样是正确的, 但这样就违背了我上面说的分类了. 因为a算是数组指针, p算是普通指针. 其实p的类型你可以看作是 int []类型的. 或者说a的类型可以看作是int *类型的. 为什么那个类型要加黑并斜体? 因为, []中间我没写数字, 那么这是为什么? 不写, 说明它中间可以是任何数字. 也就是说, 可以是10, 所以int *p = a是成立的. 同样: int a[10][20]; int (*b)[20] = a; 这样亦是成立的.因为*b可以看作是[]这样int (*b)[20]就可以看作是int b[][20]而[]中间可以是任何数字, 所以这样作成立. 那么, 为什么要加那个括号? 因为, []的优先级和*不一样[]比*要高.如果不加括号, 它的意思是: 而我们是想让它 指向 一个元素为10的一维数组, 且这个一维数组的各个元素也是一个长度为20的一维数组 为什么这里我没有用建立?因为它在上一行已经建立过了, 这里 仅仅是指向它

  • 04

    我们知道, 多维数组并不存在, 而是一维数组又套着一维数组.二维数组也是二级指针的一种, 三维数组也是三级指针的一种, 但它们又不是. 因为赋值的时候会报错. 如: int i; int *p = &i; int **q = &p; int a[10][20] = {{0}}; q = a;  //错误.因为a是int[10][20]型的, 而q是int **型的(也是int [1][1]) 那么为什么要作这个区别?原因很简单, 因为数组要取值. # define A 10 int a[A] = {0}; int i = rand() % A; a[i] == *(a+i);      //这一句永远是真. 也就是说a[i]永远等价于*(a+i)那么二维数组呢? int a[10][20]; a[10]得到的是一个指针, 它不类型不是int *, 而是int[20].为什么要作这个区分?下面的代码看过后, 相信你就知道了. a[i][j]; *( *(a+i) + i*j) ); 这句很乱, 我们先把这些变量的类型说下, a: int[10][20], i: int, j: int. 也就是说a是一个二级指针.它加一个*是指针, 再加一个才是有用的数据.所以 *(a+i): int [20] (指向数组的指针)  我们把这个表达式执行后的结果用X表示 那么: *( X + i*j)的类型就是int型. 类型X是int [20], 也就是个一级指针 (上一页的斜黑体字)指针再加个*, 那就是它所指向的数据.

  • 05

    上一页的一些知识可能会没看懂, 这里我再说些别的. 这个知识点用我的话说就是: 每一个表达式都有值为什么?因为:1 + 2+ 3这个表达式再简单不过了, 但其实它和上一页的内容就有关系. 1 + 2+ 3, 因为都是+号, 所以优先级一样. 而+的结合顺序是从左到右, 所以先执行1+2, 1+2的结果是3, 所以剩下部分就是 3 + 3其中第一个3是1+2的结果, 后面的3是我们代码中的3. 3+3的结果是6, 所以这个语句的结果就是6. 而void, 它也是一种类型, 自我感觉它也是占空间的, 应该是1字节, 内容为0.也就是NULL ()

  • 06

    然后这里再说说关于字符串(字符指针) 为什么我要把这个内容放到这个文章, 并且是最后?因为字符串和 我说过的这些知识都有关系.. 为什么?从很多地方都可以得到证明: char *= "abcdefghi"; int printf( const char*, ...); 还有一点, 学过C++的都可以试试: char ch = 'a'; char a[10] = "bcdefghij"; char *p = &a; cout<<p<<endl; 输出的不是ch的地址, 而是abcdefghij . 这个其实用C语言也可以表现出来, 但是没有C++更好理解, 因为C++的cout类输出不用写类型, 而C语言要写输出类型. 因为你要输出ch的地址, 用的肯定是%p, 所以它就直接用unsigned int的解码方式去输出收到的参数. 所以就不会输出字符串了. 如果要用C语言实现, 把最后一句改成: printf(" %s", p); %s, 而不是 %p 别的我就不再一一说出了.那么字符串和字符指针, 字符又有什么关于呢? 就拿char *ch = "abcdefghi"; 这个语句来说吧.ch其实是指向a的. 也就是说*ch == 'a'; 而字符串 一定是 连续的, 所以a的后面就是b, *(ch + 1) == 'b', 或者是ch[1] == 'b' 如果用代码实现字符串的输出, 我认为大家就会完全明白了: int myprintf (const char*c){    int i;    for (i=0; c[i] != '\0'; i++)    {        putchar (c[i]);    }    return i + 1;} 其中返回值要不要都可以. 现在再回来char *ch = "abcdefghi"这个定义中来. 这个定义执行后, 程序中是多出了14个字节的空间. 其中4字节保存ch, ch中保存的就是a的地址. 剩下10字节, 9字节保存有效字符a-i, 还有一字节保存\0. 而保存字符串的那10字节的空间是 只读的这个关于的字面量池. 有兴趣的可以看一看. 如果没有兴趣看的, 就记住:char *name = "xxxx";的定义中, 除了name指向的字符是不可改变的, 因为: char *p = "abc"; char *q = "abc; p和q是 相等的这是为了节省空间. 只保存一个备份. 但是你如果改变了p指向变量的值, 编译器是不会报错的, 运行的时候才会出错, 所以我们要么不这样定义, 要么在前面加上const修饰. 当然, 请一定要加上const. 因为编译器是有设置的, 如果工程设置中设置了只留一个备份, 那么它就是只读的, 如果是一个指针分配一个字符串, 那么这样就是可读可写的. 但这样移植性差, 大多编译器的初始设置都是留一个备份的.

(0)

相关推荐

  • xp中点击开始菜单将鼠标指针停在所有程序上子菜单没有自动弹出

    在 Windows XP 中,点击“开始”菜单,然后将鼠标指针停在“所有程序”上,“所有程序”并没有自动弹出菜单,而是通过点击“所有程序”才会显示其菜单。同样,如果想打开 “所有程序”中的子菜单,也是 ...

  • Win8鼠标指针华丽变身 比Win7更帅气好看

    还真不习惯微软对版本命名的变化,熟悉了Alpha、Beta、RC,现在微软偏偏给你整个Win8 DP、CP、RP。总之名字就是代号而已,姑且这么默默接受吧。 自从2月29日微软发布Windows 8消 ...

  • 怎么安装鼠标指针具体该怎么操作

    打开鼠标方案所在的文件夹,在其中找到“AutoSetup.inf”,在其上单击鼠标右键,然后从快捷菜单选择“安装”。(注:如果有“打开文件-安全警告”,则按该弹出窗口的“打开”按钮。) 在安装复制完成 ...

  • Excel 单元格指针移动方式介绍

    在工作表中,每一个单元格保存有一个数据,在使用工作表时我们需要在这些单元格中移动到达目的地址,Excel内单元格指针的移动有多种方式,下面我们分别进行介绍。 3.2.1 在显示范围内移动 如果目的单元 ...

  • 怎样修改win7鼠标指针 win7鼠标指针怎么换

    win7的美化对于每个用户来说都那么重要,正是因为它的界面效果才迎来了许多用户的喜爱,喜欢美化桌面的朋友可以通过替换元素的方式修改鼠标各项指针,包括指针、后台、忙等状态,为你的桌面添上一道靓丽的风景。 ...

  • 在Word2007中如何使用或消除智能指针编程功能

    智能指针是Word中的一项编程功能,用户可以在Word2007中启用或取消智能指针功能,操作步骤如下所述: 第1步,打开Word2007文档窗口,依次单击“Office按钮”→“Word选项”按钮,如 ...

  • 如何解决Win8.1下玩游戏鼠标指针冻结或者明显延迟的问题

    这个更新可以修正以下游戏中的鼠标问题: Call of Duty: Black Ops(使命召唤7:黑色行动) Call of Duty: Black Ops II(使命召唤9:黑色行动2) Call ...

  • 如何把鼠标指针改为系统默认样式(图文教程)

    简介 现在的电脑系统主题越来越多,也越来越花哨,一般的主题制作时就会把鼠标样式更改了,导致很多人纠结一个问题,很想要现在主题其它样式,唯独鼠标指针想要默认的,但不知道如何去改。今天就教大家如何更改。 ...

  • win8切换主题(桌面图标/鼠标指针)也随着改变了的解决方法

    在 Windows 8 中只可以把桌面图标锁定,但鼠标指针会随着更改主题而变化。 操作步骤: 1、在桌面上右键,单击“个性化”。参考下图所示 2、在“个性化”里单击“更改桌面图标”。参考下图所示 3、 ...

  • 如何在Word2010中设置使用智能指针功能

    智能指针是Word中的一项编程功能,用户可以在Word2010中启用或取消智能指针功能,操作步骤如下: 第1步,打开Word2010文档窗口,依次单击“文件”→“选项”命令,如图2011122801所 ...