在上一篇文章<由只北一样的表达式说开去>中提到了"序列点"和“未定义”这两个概念,而且好像有点难理解的样子,在这篇文章就理一下相关概念。
首先是"序列点
":序列点是一个时间点,此刻操作完成,所有的副作用都已确保结束。C语言标准中提及的序列点包括:1、完整表达式(表达式语句或不为任何其他表达式的子表达式的表达式)的尾部;2、||、&&、?:或逗号操作符处;3、函数调用时(参数求值完毕,函数被实际函数调用前)。ANSI C标准有这样的描述:在上一个序列点和下一个序列点之间,一个对象所保存的值至多只能被表达式的求值修改一次,而且只有在确定将要保存的值的时候才能访问前一个值。这句话的前半句就排除了诸如:i++*i++和i = i++这样的
表达式,在两个序列点之间,两个表达式中的i的值都被修改了两次。后半句要表达的意思是:如果对某个对象需要写入一个完整表达式中,则在同一个表达式中对该对象的访问应该局限于用来计算将要写入的值,这就有效的限制了只有能在确保修改之前才访问变量的表达式为合法的表达式
,禁止了像:a[i
] = i++这样的表达式。因为在这个表达式中,对i的访问和最终对i值的写入木优一点关系,也就是说,在这次访问中,并没有神马好的方法来确定对i的访问是在i值写入之前还是之后。所以在ANSI C
标准
中将这种表达归为“未定义”的。好吧,那神马叫做
“未定义”?
C语言中有3种情况来表示没有明确要求某个特定构造或者使用它的程序必须要完成的事情的领域。具体是:实现定义的、未定义的、不确定的
。
实现定义的:实现必须选择某种行为,对程序不能编译失败,这种选择必须要有
文档说明。不确定的:跟未定义相似,但无需有文档说明。未定义的:任何事情都有可能发生,标准对此没有任何要求,程序可能编译失败,可能发生运行时错误、也有可能如你所期望的那样运行,这样的代码是比较危险的。因为,你不能保证它在你希望它不出错的时候不出错。
so,应该尽量不要让这种代码出现在你的程序里。
分享到:
相关推荐
C语言序列点总结 序列点是C语言中的一个重要概念,它指的是程序运行中的一个特殊时间点,在该点之前的所有副作用已经结束,并且后续的副作用还没发生,而两个序列点之间所有的表达式或代码执行顺序是未定义的。 副...
在教学中,引入序列点的概念可以帮助学生深入理解C语言的表达式求值规则,避免因混淆操作符优先级和序列点而导致的错误。掌握序列点对于解决复杂表达式、编写高效代码以及调试程序都至关重要。在编写涉及副作用的...
例如,当一个表达式中对同一个变量多次自增或自减时,编译器可能在不同的序列点对变量进行操作,这就产生了未定义行为。 未定义行为也是计算机编程中的一个微妙话题,它涉及许多看似合理却具有不确定性行为的计算机...
综上所述,文章通过分析C语言在教学过程中关于运算符及表达式的一些误区,并引入序列点和副作用这两个概念,来澄清了C语言表达式求值过程中的模糊认识,帮助读者更好地理解和掌握C语言的编程技巧。通过对这些概念的...
- 在C语言中,复杂表达式的理解需要对运算符优先级、结合性和序列点有深入的理解。 - 对于变量的自增,`++i`和`i++`的区别在于前者先增加后使用,后者先使用后增加。 4. 指针 - 指针的声明和内存分配应正确使用`...
通过上述分析,我们可以看到,这些练习题覆盖了C语言的基础语法和编程实践中的关键概念,对于掌握C语言具有重要意义。学习者应通过实践加深对这些知识点的理解,并逐渐提高解决复杂问题的能力。
字符串在内存中是连续存储的字符序列,因此,通过指针遍历字符串时,应小心不要超出数组边界,否则可能会导致未定义行为。 5. 避免混淆指针和指针所指的值 在使用指针时,要清楚区分指针变量(如`s`)和指针所指向...
4. 混淆字符和字符串:C语言中的字符常量是由一对单引号括起来的单个字符,而字符串常量是用一对双引号括起来的字符序列。 5. 在引用数组元素或指针变量之前没对其赋初值:在C语言中,数组元素或指针变量必须在使用...
由于自增运算符具有副作用(即改变了变量的值),而C语言标准规定了对于带有副作用的表达式在没有序列点的情况下,其求值顺序是未定义的,这就导致了上面这行代码的不确定性。 除此之外,文档中还提到了一些其他的...
- C语言中的序列点是确定表达式中操作顺序的一个概念,理解它对于编写可靠代码至关重要。 - 指针和数组在表达式中的行为需要特别注意,尤其是指针自增运算符的使用。 5. 指针和内存分配 - 指针是C语言的核心概念...
C语言调试是C语言程序设计中非常重要的一步骤,对于初学者来说尤其重要。C语言调试常见错误主要可以分为两类:第一个类错误是编译时错误,第二个类错误是运行时错误。本文将对C语言调试常见错误进行分类和讲解,...
1. **运算符的优先级和序列点**:在C语言中,运算符具有确定的优先级,同时需要理解序列点的概念,以避免未定义行为。 2. **赋值和自增操作**:`a[i] = i++;` 这样的表达式会因为序列点的问题导致未定义行为。`++i` ...
中存在序列点问题,根据C语言标准,结果是未定义的,因此这样的操作应避免。 - 递增操作符++i和i++的区别在于,前者是先将变量增加1再返回变量值,后者是先返回变量值再将变量增加1。 - 位异或运算符ˆ可以用来...
标题《C语言字符、字符串定义及相关函数》所涉及的知识点主要集中在C语言中字符与字符串的表示方法、存储机制以及常用的字符串操作函数。C语言是高级编程语言中较为底层的一门语言,它没有专门的字符串类型,而是...
在C语言中,指针是一个至关重要的概念,它允许我们直接操作内存地址,实现高效的数据处理和复杂的程序设计。指针常量和指针变量是C语言中指针的两个主要类型,理解它们的区别和联系对于掌握C语言至关重要。 首先,...
本项目是用C语言编写的一个C语言词法分析器,它能够读取C源代码文件,并将源代码分解成一系列有意义的符号,即词法单元,为后续的语法分析和编译过程做准备。 词法分析器的主要任务是识别源代码中的标识符、常量、...