第三章: 语义陷阱

  3.1 Pointers and arrays: (指针和数组陷阱)

在C语言中,数组和指针的意义是相互联系的:

1)、C 语言只有一维数组,而且数组的元素个数必须在编译之前用一个定值给出( 静态数组 );

但是数组中可以包括数组( 即二维数组 );

2)、事实上,数组只能做两件事情: 声明数组中元素个数 和 得到一个数组的头指针;

其他的操作,实际上是由指针来完成的;( 尽管有一些看起来是数组实现的! )

例:

p = a;

a[ i ] = 84;          等价于     *( p + i ) = 84;

1. 数组的声明:    int a[ 3 ];

2. 二维数组的声明 : int calendar[ 12 ][ 31 ];

注:    

此处表示为 : calendar 含有十二个数组,而每一个数组中又单独包括31一个元素;

          3. 数组名:

除了在 sizeof( ) 中使用之外,数组名都表示指向它所代表的数组的首个元素的地址的指针;

并且当一个指针指向了一个数组之中的元素时:

   当指针加 1 时,并不是地址数加 1; 而是指向数组中的下一个元素;


注:

当使用数组名赋值给一个指针时 :  p = a; 是允许的;

                                   但是 : p = &a; 是错误的!   

因为 a 已经表示了地址, 而 &a 表示指向一个数组的指针,但是对于 p 来说,表示一个指向 int类型的指针

          4. 数组名在 sizeof 中的使用:

对于一般情况下,数组名既代表了首个元素的地址的指针;

但是对于 sizeof(a) 其表示的是:整个数组元素的大小,而非一个指针的大小!

   5. 二维数组与指针:

对于二维数组 : int  calendar[ 12 ][ 31 ];   那么  calendar[ 4 ]的取值为如何呢?

事实上,calendar[ 4 ] 是一个包括了 31 个 int 元素的一位数组;

所以我们可以有:

int *p;     p  = calendar[ 4 ];

或者:

int i;        i = calendar[4][7];   equals to   i = *( *(calendar + 4) + 7 );

注:

           对于 p = calendar;    这个语句是错误的,因为 calendar 是一个指向 数组的指针,而 p 是一个指向 int 的;

例: 清除一个由二位数组表示的日历:

int month;

for(month = 0; month < 12; month++)

{

int day;

for( day = 0; day < 31; day++  )

{

calendar[month][day] = 0;

}

}

当利用指针来表示的时候,我们可以有:

int (*monthp) [31];

for( monthp = calendar ; monthp < &calendar[12] ; monthp++ )

{

int *dayp;

for( dayp = *monthp; dayp < &monthp[31]; dayp++ )

{

*dayp = 0;

}

}

  3.2 Pointers are not arrays : (指针不完全等于数组)

在C语言中, 对于一个字符串,在最末尾会自动加上一个 ‘\0’;这可能出现很多问题:

          1. 我们有两个字符串 : s 和 t ,并且我们期望能把它们合并成一个字符串 r;

1):考虑方法:

char *r;

strcpy(r,s);

strcat(r,t);

则会产生错误: 因为在使用 r 时,r 没有指向任何被分配的空间区域!

2):修改:

char r[1000];

strcpy(r,s);

strcat(r,t);

即: 将 r 分配一段连续的空间,并指向首元素;但此时 空间仍然有容量限制!

3):再次修改:( 使用malloc 函数 )

char *r,*malloc();

r = malloc( strlen(s) + strlen(t) );

strcpy( r,s );

strcat( r,t );

这个程序仍旧错误: 首先:malloc 可能无法分配足够的空间而返回一个 NULL指针;

                                 其次:在使用结束后,要使用 free 来释放空间!

                                 第三:这个malloc语句没有提供足够的空间!!

对于函数 strlen ,在计算字符串长度的时候,是不计算 '\0' 的空间的;

       

所以:  当 strlen(s) 取值为 n 时, 实际需要的存储空间为 n + 1;

4):最终方案:

char *r, *malloc( ) ;

r = malloc( strlen(s) + strlen(t) + 1 );    // 对应错误3

if( !r )          // 对应错误1;

{

complain();

exit(1);

}

strcpy(r,s);

strcat(r,t);

...............

free(r);       // 对应错误2;

  3.3 Array declarations as parameters : (数组与参量陷阱)

在C语言中,我们无法直接在函数中引用整个数组,但是我们可以通过数组名的方式引入指针:

例:

char hello[ ] = "hello";

printf( "%s\n ", hello );     equals to   printf( "%s\n" , &hello[0] );

对于形参,我们有:

int strlen( char s[ ] )   equals to    int strlen( char *s );

注: 对于:


     extern char *hello;            defferent from   extern char hello[ ];

  3.4 Eschew synecdoche : (避免代换)

对于两个指向同一个存储空间的指针相互赋值,其指向的存储空间并不会被复制!

  3.5 Null pointers are not null strings : (空指针不是空字符串!)

        当给一个指针直接赋值常量时,通常是与实现功能无关的,但是要注意给指针赋值 0;

通常我们有: #define NULL 0

        即将某个指针变为空指针;!

此时,在使用空指针的时候,一定要注意:

                Not ask what is in the memory it addresses!

例如:

        对于:         if( p == ( char *)  0 )        是允许的!

但是对于:         if( strcmp( p , ( char *) 0 )  == 0 )         是非法的,因为函数 strcmp 要寻找 p 的指向区域!

3_Semantic Pitfalls 语义错误相关推荐

  1. C语言中的语法错误和语义错误

    语法错误 1:如果不遵循C语言的规则就会犯语法错误,它类似于英语中的语法错误. 例如(Bugs frustrate be can)这句英语 可以看出句子中的英语单词都是正确的,但是没有按照正确的顺序组 ...

  2. 语法错误与语义错误(所有语言通用版)

    目录: 导言: 语法错误: 语义错误: 区分语法错误与语义错误: 语义错误很可怕: 导言: 在我们日常写代码的日子里,难免会写出然我们意想不到的Bug(错误)但你也不需要担心,我们每一次写完Bug之后 ...

  3. 对比语法错误、语义错误以及运行时错误

    翻译人员: 铁锚 翻译日期: 2013年12月4日 原文链接:  Syntactic vs. Semantic vs. Runtime Errors 下面的三个例子演示了什么是语法错误.什么是语义错误 ...

  4. 语法错误和语义错误区别

                                       语法错误和语义错误区别  1.语法错误 语法错误在编程环境下,会在编译期被发现 在编程语言中,语法错误一定只在编译期时出现,编译器 ...

  5. linux不编译设备树,petalinux 编译时报设备树语义错误

    大家好,我使用petalinux 2017.3 编译时出现如下错误,请问这个有人遇到吗? 一,编译之后报错如下: liuwei@ubuntu:~/project/wasa2_readout_firmw ...

  6. c语言中的语义错误和语法错误,C语言程序中对错误的调试

    程序调试 现在我们已经可以编写一个简单的 C语言程序了,但是你可能会犯一些简单的错误.程序的错误通常叫做 bug,而发现和修正这些错误的过程叫做调试.下面有一个带有一些错误的程序,看看你能找出多少. ...

  7. 深入探讨Java中的异常与错误处理

    Java中的异常处理机制已经比较成熟,我们的Java程序到处充满了异常的可能,如果对这些异常不做预先的处理,那么将来程序崩溃就无从调试,很难找到异常所在的位置.本文将探讨一下Java中异常与错误的处理 ...

  8. python语法错误概述_Python 错误和异常代码详解

    程序中的错误一般被称为 Bug,无可否认,这几乎总是程序员的错... 程序员的一生,始终伴随着一件事 - 调试(错误检测.异常处理).反反复复,最可怕的是:不仅自己的要改,别人的也要改...一万头草泥 ...

  9. c语言调试出错误怎么改,C语言调试常见错误及修改方法(附习题)

    <C语言调试常见错误及修改方法(附习题)>由会员分享,可在线阅读,更多相关<C语言调试常见错误及修改方法(附习题)(12页珍藏版)>请在人人文库网上搜索. 1.1.调试C程序时 ...

最新文章

  1. JAVA条件表达式的陷阱
  2. 模块加载过程代码分析1
  3. 剑指Offer - 面试题61. 扑克牌中的顺子
  4. 数据库中char, varchar, nvarchar的差异
  5. android design包控件,Android Design包之TextInputLayout和TextInputEditText的组合使用【原创】...
  6. 物联网设备获取北京时间、年月日、星期几,GMT格林威治标准时间转换为北京时间,授时api Fiddler抓包调试
  7. 使用Sphinx对MySQL数据库进行全文检索
  8. [ 常用工具篇 ] Esxi 安装详解
  9. 中国制药机械行业发展态势与运营展望分析报告2022版
  10. kubelet源码分析(四)之 syncLoopIteration
  11. 【技术】客服服务开发
  12. 如何快速提高Python能力
  13. c语言字符串atoi函数,C++_C语言中一些将字符串转换为数字的函数小结,C语言atoi()函数:将字符串转换 - phpStudy...
  14. 【鼠标事件 MouseEvent】clientX clientY offsetX offsetX pageX screenX screenY
  15. Yobili优碧俪打造轻奢营养食品,以品质破圈
  16. Vi编辑异常退出解决
  17. 程序猿和测试媛——组合在一起的原因
  18. Camera中onPreviewFrame()方法的视频方向旋转
  19. mysql情况数据库表数据函数_mysql数据库表单查询和函数的使用
  20. 审稿审什么你真的弄清楚了吗

热门文章

  1. 数据库系统的内部体系(三级模式二级映像)
  2. 【181125】VC++ 绘制立方体的生成与控制旋转程序源代码
  3. 2023,再转行去做软件测试还有前途吗?
  4. 常用触摸屏驱动 android
  5. 全国一级计算机基础及MSOffice应用模拟软件下载
  6. oracle数据库some,【案例】Oracle报错Some indexes or index [sub]partitions of table VAS.TAB_PUB_CALLLOG...
  7. Spark on YARN - Clinet模式运行spark报错问题
  8. 拉我室友打了一把英雄联盟搞会了IntelliJ IDEA的安装与配置
  9. ECCV2018 | PKT_概率知识蒸馏
  10. 通过OCR识别技术 识别视频和图片的文字信息怎样得到结果