3_Semantic Pitfalls 语义错误
第三章: 语义陷阱
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 语义错误相关推荐
- C语言中的语法错误和语义错误
语法错误 1:如果不遵循C语言的规则就会犯语法错误,它类似于英语中的语法错误. 例如(Bugs frustrate be can)这句英语 可以看出句子中的英语单词都是正确的,但是没有按照正确的顺序组 ...
- 语法错误与语义错误(所有语言通用版)
目录: 导言: 语法错误: 语义错误: 区分语法错误与语义错误: 语义错误很可怕: 导言: 在我们日常写代码的日子里,难免会写出然我们意想不到的Bug(错误)但你也不需要担心,我们每一次写完Bug之后 ...
- 对比语法错误、语义错误以及运行时错误
翻译人员: 铁锚 翻译日期: 2013年12月4日 原文链接: Syntactic vs. Semantic vs. Runtime Errors 下面的三个例子演示了什么是语法错误.什么是语义错误 ...
- 语法错误和语义错误区别
语法错误和语义错误区别 1.语法错误 语法错误在编程环境下,会在编译期被发现 在编程语言中,语法错误一定只在编译期时出现,编译器 ...
- linux不编译设备树,petalinux 编译时报设备树语义错误
大家好,我使用petalinux 2017.3 编译时出现如下错误,请问这个有人遇到吗? 一,编译之后报错如下: liuwei@ubuntu:~/project/wasa2_readout_firmw ...
- c语言中的语义错误和语法错误,C语言程序中对错误的调试
程序调试 现在我们已经可以编写一个简单的 C语言程序了,但是你可能会犯一些简单的错误.程序的错误通常叫做 bug,而发现和修正这些错误的过程叫做调试.下面有一个带有一些错误的程序,看看你能找出多少. ...
- 深入探讨Java中的异常与错误处理
Java中的异常处理机制已经比较成熟,我们的Java程序到处充满了异常的可能,如果对这些异常不做预先的处理,那么将来程序崩溃就无从调试,很难找到异常所在的位置.本文将探讨一下Java中异常与错误的处理 ...
- python语法错误概述_Python 错误和异常代码详解
程序中的错误一般被称为 Bug,无可否认,这几乎总是程序员的错... 程序员的一生,始终伴随着一件事 - 调试(错误检测.异常处理).反反复复,最可怕的是:不仅自己的要改,别人的也要改...一万头草泥 ...
- c语言调试出错误怎么改,C语言调试常见错误及修改方法(附习题)
<C语言调试常见错误及修改方法(附习题)>由会员分享,可在线阅读,更多相关<C语言调试常见错误及修改方法(附习题)(12页珍藏版)>请在人人文库网上搜索. 1.1.调试C程序时 ...
最新文章
- JAVA条件表达式的陷阱
- 模块加载过程代码分析1
- 剑指Offer - 面试题61. 扑克牌中的顺子
- 数据库中char, varchar, nvarchar的差异
- android design包控件,Android Design包之TextInputLayout和TextInputEditText的组合使用【原创】...
- 物联网设备获取北京时间、年月日、星期几,GMT格林威治标准时间转换为北京时间,授时api Fiddler抓包调试
- 使用Sphinx对MySQL数据库进行全文检索
- [ 常用工具篇 ] Esxi 安装详解
- 中国制药机械行业发展态势与运营展望分析报告2022版
- kubelet源码分析(四)之 syncLoopIteration
- 【技术】客服服务开发
- 如何快速提高Python能力
- c语言字符串atoi函数,C++_C语言中一些将字符串转换为数字的函数小结,C语言atoi()函数:将字符串转换 - phpStudy...
- 【鼠标事件 MouseEvent】clientX clientY offsetX offsetX pageX screenX screenY
- Yobili优碧俪打造轻奢营养食品,以品质破圈
- Vi编辑异常退出解决
- 程序猿和测试媛——组合在一起的原因
- Camera中onPreviewFrame()方法的视频方向旋转
- mysql情况数据库表数据函数_mysql数据库表单查询和函数的使用
- 审稿审什么你真的弄清楚了吗
热门文章
- 数据库系统的内部体系(三级模式二级映像)
- 【181125】VC++ 绘制立方体的生成与控制旋转程序源代码
- 2023,再转行去做软件测试还有前途吗?
- 常用触摸屏驱动 android
- 全国一级计算机基础及MSOffice应用模拟软件下载
- oracle数据库some,【案例】Oracle报错Some indexes or index [sub]partitions of table VAS.TAB_PUB_CALLLOG...
- Spark on YARN - Clinet模式运行spark报错问题
- 拉我室友打了一把英雄联盟搞会了IntelliJ IDEA的安装与配置
- ECCV2018 | PKT_概率知识蒸馏
- 通过OCR识别技术 识别视频和图片的文字信息怎样得到结果