C和指针第6章笔记

第6章学习指针的基础知识。

书籍摘录

  1. 内存中的每个位置由一个独一无二的地址标识。
  2. 内存中的每个位置都包含一个值。
  3. 用一个单一的值标识两种不同的意思很危险,将来容易无法弄清哪个才是他的真正用意。
  4. 对一个null指针进行解引用操作是非法的。在对指针进行解引用(*)操作之前,先先保证其不是null指针。
  5. (*b)是一个地址,如果*b=&a,那么代表这个指针是指向变量a的。
  6. char ch = 'a';中,ch可以作为右值使用,表达式的值是’a’,另外也可作为左值使用此时他的值就是这个变量的地址。书中用图片描述,右值是里边的小圆圈,左值是包含这个小圆圈的方格子。
  7. 间接访问操作符(*)是少数几个其结果为左值的操作符之一(P122
  8. 指针加上一个整数的结果是另一个指针。
  9. 调整的美感在于指针算法并不依赖于指正类型。这个行为较之获得一个指向一个float值内部某个位置的指针更为合理。
  10. 标准允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针进行比较,但不允许与指向数组第1个元素之前的那个内存位置的指针进行比较。
  11. 只有当两个指针都指向同一个数组中的元素时,才允许从一个指针减去另一个指针。

问题

  1. 如果一个值得类型无法简单地通过观察它的位模式来判断,那么机器是如何知道应该怎样对这个值进行操纵的?
    • 机器无法做出判断。编译器根据值的声明类型创建适当的指令,机器只是盲目的执行这些指令而已。
  2. C为什么没有一种方法来声明字面值指针常量呢?
    • 关于“字面值指针常量”,我的理解是地址的具体信息,把一个指针量直接设置成某某地址。这很麻烦,而且没必要。
    • they are rarely used because you can’t tell ahead of time of where the compiler will put variables.(它们很少使用,因为您无法提前告知编译器将变量放在何处。)
  3. 假定一个整数的值是244。为什么机器不会把这个值解释为一个内存地址呢?
    • 也许是因为有声明整数类型,编译器不会对其进行解引用操作
    • the value is an integer,so the compiler will not generate instructions to dereference it.
    • dereference [间接引用,间接访问,解引用obtain from (a pointer) the address of a data item held in another location.]
  4. 在有些机器上,编译器在内存位置零存储0这个值。对NULL指针进行解引用操作将访问这个位置。这种方法会产生什么后果?
    • 啥是“零存储”,还是位置零 存储0?后者,题目中说访问这个位置,注意审题。
    • 这是很危险的。首先,解引用一个NULL指针的结果因编译器而异,所以程序不应该这样做。允许程序在这样访问之后还能继续运行是很不幸的,因为这时程序很可能并没有正确运行。
  5. 见书[P113]
    • 有效率上的差别
    • Even if ‘offset’ has the same value as the literal in the next expression, it is more time consuming to evaluate the first expression because the multiplication to scale ‘offset’ to the size of an integer must be done at run time. This is because the variable might contain any value, and the compiler has no way of knowing ahead of time what the value might actually be. On the ohter hand, the literal three can be scaled to an integer by multiplying it at compile time, and the result of that multiplication is simply added to ‘p’ at run time. In other words, the second expression can be implemented by simply adding 12 to ‘p’(on a machine with four-byte integers); no runtime multiplication is needed.(即使”偏移”的值与下一个表达式中的文本值相同,计算第一个表达式也更加耗时,因为在运行时必须完成将”偏移量”缩放为整数大小的乘法。这是因为变量可能包含任何值,编译器无法提前知道该值实际上可能是什么。另一方面,文字三可以通过在编译时乘以整数将其缩放为整数,并且该乘法的结果在运行时仅添加到”p”。换句话说,第二个表达式可以通过简单地将 12 添加到”p”(在具有四字节整数的计算机上)实现;不需要运行时乘法。)
  6. 见书[P113]是一个基本的++操作问题
    • 第一个位置应该没有赋值成0,先加后赋值了。一般后边还会越界。
    • 有两个错误。对增值后的指针进行解引用时,数组的第1个元素并没有被清零。另外,指针在越过数组的右边界以后仍然进行解引用,它将把其他某个内存地址的内容清零。
  7. 见书[P114] *,&,++,()等操作符的练习
    • 温故知新吧,之后放个截图,偶尔看看

编程练习

  1. 请编写一个函数,它在一个字符串中进行搜索,查找所有在一个给定字符集合中出现的字符。这个函数原型应该如下:
    1
    2
    char 	*find_char( char const *source,
         char const *chars );
    

    a. 不能使用库函数(strcpy,strcmp,index) b. 别用下标引用,练习操作指针。

  • 程序如下:
    1
    2
    3
    4
    5
    6
    #include<stdio.h>
    int
    main()
      {
          // 不能有空行
      }
    

参考链接

查询的链接:

TortoiseGit保存用户名和密码的方法