Pointers on C(第八章 第九章 第十章 第十一章 第十二章)

第八章 数组

 

1、数组名是一个指针常量,也就是数组第一个元素的地址,而不是指针变量。

 

2、sizeof 数组名:返回整个数组的长度,而不是指向数组的指针的长度。

 

   sizeof string:返回的是指向字符的指针的长度,而不是数组的长度。

 

3、不能使用赋值符把一个数组的所有元素赋值到另一个数组。


   如:int a[10];
       int b[10];
       b=a; //错误

 

4、一个神秘和离题的例子:


   2[array] 是合法的。相当于array[2].

 

5、函数原型中的一维数组形参无需写明它的元素数目,因为函数并不为数组参数分配内存空间。


   在多维数组中,只有一维数组才能根据初始化列表缺省地提供,剩余的几维必须显示地写出,这样编译器就能推断出每个子数组维数的长度

 

6、不完整的初始化,只允许省略最后几个初始值。


   如:int vector[4]={1,5};

 

7、int d[3][6][10];


   d是一个3排6列10行的整型三维数组。


   多维数组的元素存储顺序按照最右边的下标率先变化的原则,---行主序。


   可以把d看成1个1维数组,有3个元素,每个数组元素是又一个数组,含有6个元素,这每个元素又是一个数组,含有   10个元素。

 

8、int matrix[3][10];

 

   1)、matirx[1][5]

 

   2)、matirx 
       它的类型是指向包含10个整型元素的数组的指针。指向包含10个整型元素的第一个子数组。

 

   3)、matrix+1
       指向包含10个整型元素的第二个子数组。

 

   4)、*(matrix+1)
       类型:指向整型的指针。
       相当于matrix[1]
  
   5)、*(matrix+1)+5
       类型:指向整型值的指针
       相当于&matrix[1][5]

 

   6)、*(*(matrix+1)+5)==matrix[1][5];

 

9、指向数组的指针

   int matrix[3][10];
   int (*p)[10]=matrix;        //p指向matrix的第一行
  
   p是一个指向(拥有10个元素整型元素的数组)的指针。


   警告: int (*p)[]=matrix;
          p仍然是指向一个整型数组的指针,但是数组长度却不见了。当某个整数与种类型的指针执行指针运算时,
          它的值将根据空数组的长度进行调整,也就是说与0相乘。结果可能不是你所设想的。

 

10、指针数组

 

    int *p[10];


    p是一个数组,含有10个元素,每个元素是指向整型值的指针。

 

11、只要有可能,函数的指针形参都应该声明为const。

 

12、在有些环境中,使用register关键字提高程序的运行效率。

 

13、在多维数组的初始值列表中使用完整的多层花括号能提高可读性。

 


第九章  字符串、字符和字节

 

1、NULL字节是字符串的终止符,但它本身不是字符串的一部分,所以字符串的长度并不包括NULL字节。


   字符串的长度就是它所包含的字符数。

 

2、size_t  strlen(char const *string);


   size_t是一个无符号整数类型。

 

   看下面两个表达式:
   if(strlen(x)>=strlen(y)) ...
   if(strlen(x)-strlen(y)>=0)...


   看似相等却不等!


   第一条语句会如你想象的那样运行。


   但是第二条语句将永远为真:因为无符号数-无符号数,结果永远都是无符号数,无符号数是不可能为负的

 

3、警告:表达式中如果同时出现了符号数和无符号数,可能会产生奇怪的结果。
   如:
      if(strlen(x)>=10)...
      if(strlen(x)-10>=0)...


   如果把strlen的返回值强制转换成int,就可以消除这个问题。

 

4、strncpy 调用的结果可能不是一个字符串,因此它的结果不会以NULL字节结尾。

 

5、提示:直接测试或操纵字符会降低程序的可移植性。


   例如:
      if(ch>='A'&&ch<='Z')


   这条语句在使用ASCII字符集的机器上能够运行,但是在使用EBCDIC字符集的机器上将会失败 。

   下面这条语句:
   if(isupper(ch))


   无论机器使用哪个字符集,它都能顺利运行。

 

6、任何类型的指针都可以转换成void*类型的指针。

 

 

 

第十章、结构和联合

1、
  struct
   {
    int a;
    char b;
    float c;
   }x;
  
  struct
   {
    int a;
    char b;
    float c;
   }y[20],*z;

    z=&x;  //这是非法的。


 上面这两个声明被编译器当做两种截然不同的类型,即使它们的成员列表完全相同。


2、点操作符的结合性是从左到右的。下标引用和点操作符具有相同的优先级,也是自左向右的结合性。它们的优先级均高于间接访问操作符。


3、struct SELF_REF{

          int a;
   struct SELF_REF b;
   int c;
   };  //这种类型的自引用是非法的。

 

  因为这样b中又有一个结构SELF_REF,以此类推,无限下去,没有结尾。


   struct SELF_REF{

          int a;
   struct SELF_REF *b;
   int c;
   };  //这种类型的自引用是合法的。

 

   这个声明和前面那个声明区别在于b现在是一个指针而不是一个结构,编译器在结构的长度确定之前就已经知道指针的长度了。

   它实际上是指向同一种类型的不同结构。(这句话是什么意思?)

 

4、不完整的声明:
   struct B;
   struct A{
      struct B;
     };

   struct B{
       struct A;
   };

 


5、优先级高到低:  ->  .  *

 

6、结构的存储分配:


   编译器按照成员列表的顺序一个接一个地给每个成员分配内存。只有当存储成员时需要满足正确的边界对齐要求时,成员之间才可能出现用于填充的额外内存空间。

 

  struct ALIGN{
       char a;
       int b;
       char c;
    };

 

 如果某个机器的整型值是4个字节长度,并且它的起始存储位置必须能够被4整除,那么


  aXXXbcXXX

 

每个结构将占据12字节的空间,但实际上只使用了其中个6个,浪费啊。。。

 

改成这样:
   struct ALIGN{
          int b;
          char a;
          char c;
  };

但它值包含了8个字节的存储空间。


两个字符字节可以紧挨着存储,所以只有结构最后面需要跳过的两个字节才被浪费掉。

 

sizeof操作符能够得出一个结构的整体长度,包括因边界对齐而跳过的那些字节。


7、什么时候你应该向函数传递一个结构而不是一个指向结构的指针呢?很少有这种情况!

 

8、位段

 

   位段成员必须声明为int、signed int、unsigned int类型。


   在成员的后面是一个冒号和一个整数。这个整数指定该位段所占用的位的数目。


   位段的声明本质上是不可移植的。

  struct CHAR{

         unsigned ch : 7;
         unsigned font:6;
         unsigned size:19;
  };

 

 

9、联合


   联合的所有成员引用的是内存中的相同位置。当你想在不同时刻把不同的东西存储与同一个位置时,就可以使用联合。

 

   如果联合的各个成员具有不同的长度,联合的长度就是它最长的成员的长度。

 

 

 

第十一章 动态内存分配

 

 

1、malloc实际分配的内存可能比你请求的稍微多一点。但是,这个行为是由编译器定义的,所以不能指望它肯定会分配比你的请求更多的内

 

存。 如果操作系统无法向malloc提供更多的内存,malloc就返回一个NULL指针。因此,动态内存分配最常见的错误就是忘记检查所请求的

 

内存是成功分配。

 

2、一个void *类型的指针可以转换为其他任何类型的指针。

 

3、malloc和calloc之间最主要的区别就是后者在返回指向内存指针之前把它初始化为0.使用realloc可以对一块内存扩大或者缩小。

 

4、释放内存的一部分是不允许的,动态分配的内存必须整块一起释放。但是realloc函数可以缩小一块动态分配的内存,有效地释放它尾部的部分内存。

 

5、分配内存但在使用完毕后不将其释放将会引起内存泄露(memory leak).

 

6、如果一个指针不是从早先的malloc、calloc、realloc函数返回的,它是不能作为参数传递给free函数的。(int *p=&a;呢?)

 

 

第十二章 使用结构和指针

 

1、Pascal语言中的指针哲学:


   使用锤子可能会伤着你自己,所以我们不给你锤子。

 

   C语言中的指针哲学:给你锤子,实际上你可以使用好几种锤子,祝你好运!

 

2、语句提炼是简化程序的一种技巧,其方法是消除程序中冗余的句子。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值