1. Q:为什么我不能对void *指针进行算术运算?

A:因为编译器不知道所值对象的大小,而指针的算法运算总是基于所指对象的大小的。

2. Q:C语言可以“按引用传参”吗?

A:不可以。严格来说,C语言总是按值传参,你可以模拟按引用传参,定义接受指针的函数,然后在调用时使用&操作符。但C没有任何真正等同于按引用传参的东西。

3. Q:怎样在整型和指针之间进行转换?能否暂时把整数放入指针变量,或者相反?

A:C标准中规定整数与指针之间的相互转换是实现定义的,因此不保证指针和整数之间无需修改就能相互转换。事实上强制进行整数和指针的相互转换从来就不是什么好的实践。当需要同时保存两种类型数据的存储结构时,使用联合是更好的办法。

4. Q:空指针到底是什么?

A:根据C语言定义,每一种指针类型都有一个特殊值——“空指针”,它与同类型的其他所有指针值都不相同,它“保证与任何对象或函数的指针值都不相等”。也就是说,空指针不会指向任何地方,它不是任何对象或函数的地址。取地址操作符&永远也不会返回空指针,对malloc的成功调用也不会返回空指针。注意,空指针在概念上不同于未初始化的指针,空指针可以确保不指向任何对象或函数,而未初始化的指针则可能指向任何地方。

5. Q:怎样在程序里获得一个空指针?

A:使用空指针常量。空指针常量可以是0或NULL(在stdio.h文件中)。根据C语言定义,在指针上下文中的“值为0的整型常量表达式”会在编译时转换为空指针。然而,传入函数的参数不一定被当作指针上下文,此时生成空指针需要显式的类型转换。下表总结了何时可以直接使用空指针常量,何时需要进行显式类型转换:

6. Q:如果NULL的值改变了,比如在使用非零内部空指针的机器上,用NULL(而不是0)不是更好吗?

A:不,尽管符号常量经常代替数字使用以备数字的改变,但这不是用NULL代替0的原因。C语言本身确保了源码中用于指针上下文的0会生成空指针。

7. Q:有没有什么简单的方法理解所有这些与空指针有关的东西?

A:遵循两条简单规则:(a) 当源码中需要空指针常量时,使用"0"或"NULL";(b) 如果在函数调用中"0"或"NULL"用作参数,把它转换成被调函数需要的指针类型。

8. Q:空指针是指向地址0的指针吗?

A:不能将空指针看作指向地址0的指针,空指针不指向任何地方。如果需要访问地址0,应该阅读厂商文档,使用机器提供的技巧来访问。

9. Q:在C语言中“指针和数组等价”到底是什么意思?

A:意思是数组和指针的算法定义使得可以用指针方便地访问数组或者模拟数组,换言之,在C语言中只是指针算术和数组下标运算等价,指针和数组是不同的。特别地,等价的基础来自这个关键定义:一个T数组类型的对象如果出现在表达式中会退化为一个指向数组第一个元素的指针,指针的类型是指向T的指针。

10. Q:如果你不能给它赋值,那么数组如何能成为左值呢?

A:术语“左值”并不完全表示“能赋值的东西”,更好的定义应该是“在内存中有特定位置的东西”。

11. Q:既然数组引用会退化为指针,如果array为数组,那么array和&array又有什么区别?

A:区别在于类型。在标准C中,&array生成一个“T型数组”的指针,指向整个数组;而array生成一个T型的指针,指向数组的首元素。

int a[];
int *pInt = a; // a的类型是"int型的指针"
int (*pArr)[] = &a; // &a的类型是"10个int的数组的指针"
int array[NROWS][NCOLUMNS];
int (*pArr2)[NCOLUMNS] = array; // array的类型是"NCOLUMNS个int的数组的指针"
int (*pArr3)[NROWS][NCOLUMNS] = &array; // array的类型是"NROWS个NCOLUMNS个int的数组的数组的指针"

12. Q:malloc(0)返回一个空指针还是指向0字节的指针?

A:ANSI/ISO标准声称它可能返回任意一种,其行为由实现定义。可移植的代码要么别调用malloc(0),要么做好它可能返回空指针的准备。

13. Q:当我调用malloc()为一个函数的局部指针分配内存时,我还需要用free()显式地释放吗?

A:是的。函数返回时,局部指针会被释放,而不是它所指的对象。用malloc()分配的内存在你显式释放它之前都会保留在那里。一般地,每一个malloc()都必须有个对应的free()调用。

14. Q:我有个程序分配了大量的内存,然后又释放了,但我发现操作系统的内存占用率并没有降低?

A:多数malloc/free的实现并不把释放的内存返回操作系统,而是留着供同一程序的后续malloc()使用。

15. Q:我的程序总是崩溃,显然发生在malloc内部的某个地方,但是我看不出哪里有问题,是malloc有bug吗?

A:很不幸,malloc的内部数据结构很容易被破坏,而由此引起的问题会十分棘手。最常见的问题来源是向malloc分配的区域写入比所分配的还多的数据,如malloc(strlen(s))而不是strlen(s)+1。其他问题包括指向已经释放了的内存的指针,分配大小为0 的对象,重分配空指针,释放未从malloc获得的指针、空指针或者已经释放的指针。这些错误的后果可能会在真正出错很久以后才显现出来或在不相关的代码段出现,从而导致排错十分困难。多数malloc的实现在这些问题面前显得十分脆弱,因为它们直接在它们返回的内存旁边存储至关重要的内部信息片段,这些信息很容易被用户指针破坏。

16. Q:free()怎么知道有多少字节需要释放?

A:malloc/free的实现会在分配的时候记下每一块的大小,所以在释放时就不必再考虑它的大小了。(通常,这个大小就记录在分配的内存块旁边,因此对超出分配内存块边界的内存哪怕是轻微的改写,也会导致严重的后果)。

17. Q:为什么sizeof不能告诉我它所指的内存块的大小?

A:sizeof操作符并不知道你使用了malloc为指针分配内存,sizeof只能得到指针本身的大小。

18. Q:动态分配数组之后,还能改变它的大小吗?

A:能,使用realloc。可以使用下边的代码。

dynarray = (int *)realloc((void *)dynarray,  * sizeof(int));

如果realloc能在原地扩大内存区域,它就返回传入的指针;如果它必须到内存中的其他地方去寻找足够大的连续空间,则它会返回一个不同的指针,而原来的指针值变得不可用;如果它根本找不到足够的空间,则它会返回空指针,而原来分配的内存会保留。因此,通常不应立即将新指针赋给旧指针,最好使用一个临时指针。

int *newarray = (int *)realloc((void *)dynarray,  * sizeof(int));
if (newarray != NULL) {
dynarray = newarray;
}
else {
fprintf(stderr, "Can't reallocate memory.\n");
/* dynarray remains allocated. */
}

《你必须知道的495个C语言问题》读书笔记之第4-7章:指针的更多相关文章

  1. 你必须知道的495个c语言问题(笔记)

    1.1我该如何决定使用哪种整数类型? 用到较大的数用long:空间很重要(例如有很大的数组或很多的结构)用short:此外用int. win32: int 32bit    4byte char 8b ...

  2. 你必须知道的495个C语言问题,学习体会一

    C语言作为一门古老的语言,其灵活性和容易出错都让人 又爱又恨,书籍<你必须知道的495个C语言问题>,使用问答的形式,告诉读者 C语言使用的各个方面的知识,包括一些冷知识等.以下,我要摘录 ...

  3. C语言学习书籍推荐《你必须知道的495个C语言问题》

    萨米特 (Steve summit) (作者), 孙云 (译者), 朱群英 (译者) 下载地址:点我 <你必须知道的495个C语言问题>以问答的形式组织内容,讨论了学习或使用C语言的过程中 ...

  4. 《你必须知道的495个C语言问题》知识笔记及补充

    1. extern在函数声明中是什么意思? 它能够用作一种格式上的提示表明函数的定义可能在还有一个源文件里.但在 extern int f(); 和 int f(); 之间并没有实质的差别. 补充:e ...

  5. 你必须知道的495个C语言问题,学习体会四

    本文,我们来学习下指针,这是个梦魇啊.无数次折磨着C语言学习者,无数次的内存泄露,无数次的访问失败,无数次的越界溢出, 这些错误造就的仅仅是一个 跟随者,真正的优秀者必须要正视语言的局限,同时在最大限 ...

  6. 你必须知道的495个C语言问题,学习体会三

    本文是 本系列的第三篇,本文主要对C语言的表达式做个小结 先从两个坑爹的表达式说起:i++ 与++i 上大学的时候,学长告诉我,这两个表达式,意义是一样的,后来老师纠正说,还是有区别的,于是让我们记住 ...

  7. 你必须知道的495个C语言问题,学习体会二

    这是本主题的第二篇文章,主要就结构体,枚举.联合体做一些解释 1.结构体 现代C语言编程 结构化的基石,diy时代的最好代言人,是面向对象编程中类的老祖宗. 我们很容易定义一个结构体,比如学生: st ...

  8. 《你必须知道的495个C语言问题》读书笔记之第11-14章:ANSI C标准、库函数、浮点数

    一.ANSI C标准 1. ANSI向C语言预处理器引入了几项新的功能,包括“字符串化”操作符(#).“符号粘贴”操作符(##).#pragma指令. 2. Q:char a[3] = "a ...

  9. 《你必须知道的495个C语言问题》读书笔记之第8-10章:字符串、布尔类型和预处理器

    一.字符和字符串 1. Q:为什么strcat(string, '!')不行? A:strcat()用于拼接字符串,所以应该写成strcat(string, "!")." ...

随机推荐

  1. java中vector中add,addElement区别

    这两个方法最大的区别就是返回值不一样,在作用上基本没有区别. add是实现List接口重写的方法,返回值为boolean.addElement是Vector类中的特有方法,返回值是void.

  2. 百度ueditor中复制word图文时图片转存任然保持灰色不可用

    官网地址http://ueditor.baidu.com Git 地址 https://github.com/fex-team/ueditor 参考博客地址 http://blog.ncmem.com ...

  3. Java进阶知识24 Spring的事务管理(事务回滚)

    1.事务控制概述   1.1.编程式事务控制         自己手动控制事务,就叫做编程式事务控制.         Jdbc代码: connection.setAutoCommit(false); ...

  4. CF1153E Serval and Snake【构造】

    题目链接:洛谷 这道题是很久以前NTF跟我说的,现在想起来把它做了... 我们发现,如果蛇的两头都在矩形里或矩形外,则询问为偶数,否则为奇数. 所以我们询问每一行和每一列,就能知道蛇的两头的横纵坐标了 ...

  5. Windows Storport Miniport 驱动开发 葵花宝典 - 翻译

    Roadmap for Developing Storport Miniport Drivers Last Updated: 4/20/2017   To create a storport mini ...

  6. 有向网络(带权的有向图)的最短路径Dijkstra算法

    什么是最短路径? 单源最短路径(所谓单源最短路径就是只指定一个顶点,最短路径是指其他顶点和这个顶点之间的路径的权值的最小值) 什么是最短路径问题? 给定一带权图,图中每条边的权值是非负的,代表着两顶点 ...

  7. MySQL inodb cluster部署

    innodb cluster是基于组复制来实现的. 搭建一套MySQL的高可用集群innodb. 实验环境: IP 主机名 系统 软件 192.168.91.46 master RHEL7.4 mys ...

  8. elasticsearch java动态设置mapping并指定分词器

    //创建索引 client.admin().indices().prepareCreate("twitter").execute().actionGet(); //配置mappin ...

  9. 【Python】使用Python处理RAW格式图片,并根据实际情况完成分组打包发送

    背景 出游之后,朋友交换的照片格式大多是RAW格式,一些人想要JPG格式,但是百度云盘非会员的下载速度惨不忍睹,所以我想着通过微信群直接传(这个在事后也被证实不能完全解决问题,微信限制了每天传递文件的 ...

  10. Axure实现提示文本单击显示后自动消失的效果

    Axure实现提示文本单击显示后自动消失的效果 方法/步骤     如图所示,框出的部分为提示文本(已经命名为tooltip),希望达到的效果是默认加载时不显示,点击帮助图标后显示,且2秒后自动消失. ...