THE EVALUATION OF OPERANDS AND ITS PROBLEMS IN C++

Similar documents
Page 1. Today. Last Time. Is the assembly code right? Is the assembly code right? Which compiler is right? Compiler requirements CPP Volatile

Important From Last Time

Page 1. Today. Important From Last Time. Is the assembly code right? Is the assembly code right? Which compiler is right?

See the CS 2704 notes on C++ Class Basics for more details and examples. Data Structures & OO Development I

Important From Last Time

6.001 Notes: Section 15.1

Introduction to Programming in C Department of Computer Science and Engineering. Lecture No. #43. Multidimensional Arrays

CS 376b Computer Vision

Deep C (and C++) by Olve Maudal

Introduction to Programming in C Department of Computer Science and Engineering. Lecture No. #29 Arrays in C

Your first C++ program

(Refer Slide Time: 4:00)

CSE 303: Concepts and Tools for Software Development

CSE 374 Programming Concepts & Tools. Hal Perkins Spring 2010

CONTENTS: What Is Programming? How a Computer Works Programming Languages Java Basics. COMP-202 Unit 1: Introduction

CSE 374 Programming Concepts & Tools. Hal Perkins Fall 2015 Lecture 19 Introduction to C++

Starting to Program in C++ (Basics & I/O)

These are notes for the third lecture; if statements and loops.

CMSC 104 -Lecture 6 John Y. Park, adapted by C Grasso

QUIZ. What is wrong with this code that uses default arguments?

T H E I N T E R A C T I V E S H E L L

CS112 Lecture: Variables, Expressions, Computation, Constants, Numeric Input-Output

Programming in C++ Prof. Partha Pratim Das Department of Computer Science and Engineering Indian Institute of Technology, Kharagpur

Introduction to Programming in C Department of Computer Science and Engineering. Lecture No. #13. Loops: Do - While

CSCI 1100L: Topics in Computing Lab Lab 11: Programming with Scratch

Review of the C Programming Language for Principles of Operating Systems

N1793: Stability of indeterminate values in C11

My malloc: mylloc and mhysa. Johan Montelius HT2016

COP 3275: Chapter 04. Jonathan C.L. Liu, Ph.D. CISE Department University of Florida, USA

Design Principles for a Beginning Programming Language

Page 1. Stuff. Last Time. Today. Safety-Critical Systems MISRA-C. Terminology. Interrupts Inline assembly Intrinsics

CS

CS112 Lecture: Working with Numbers

CS 220: Introduction to Parallel Computing. Arrays. Lecture 4

Introduction to Programming in C Department of Computer Science and Engineering. Lecture No. #17. Loops: Break Statement

3.Constructors and Destructors. Develop cpp program to implement constructor and destructor.

Instantiation of Template class

PIC 10A Objects/Classes

Introduction to Programming using C++

CSE 303: Concepts and Tools for Software Development

Lecture 19 CSE August You taught me Language, and my profit on t is I know how to curse. William Shakspere, The Tempest, I, ii.

Iteration. Side effects

Programming in C++ Prof. Partha Pratim Das Department of Computer Science and Engineering Programming in C++ Indian Institute of Technology, Kharagpur

CSE 374 Programming Concepts & Tools

Loops. In Example 1, we have a Person class, that counts the number of Person objects constructed.

A Fast Review of C Essentials Part I

CS Final Exam Review Suggestions - Spring 2014

CS107 Handout 08 Spring 2007 April 9, 2007 The Ins and Outs of C Arrays

Introduction to C++ Introduction to C++ 1

CS 430 Computer Architecture. C/Assembler Arithmetic and Memory Access William J. Taffe. David Patterson

Chapter 2 Basic Elements of C++

Language Extensions for Vector loop level parallelism

Variables and Data Representation

Lab#5 Due Wednesday, February 25, at the start of class. Purpose: To develop familiarity with C++ pointer variables

D Programming Language

Supporting Class / C++ Lecture Notes

2SKILL. Variables Lesson 6. Remembering numbers (and other stuff)...

Functions and Recursion

11. Arrays. For example, an array containing 5 integer values of type int called foo could be represented as:

Arithmetic Operators. Binary Arithmetic Operators. Arithmetic Operators. A Closer Look at the / Operator. A Closer Look at the % Operator

A brief introduction to C programming for Java programmers

What are the characteristics of Object Oriented programming language?

Control Flow. COMS W1007 Introduction to Computer Science. Christopher Conway 3 June 2003

6.001 Notes: Section 1.1

CE221 Programming in C++ Part 2 References and Pointers, Arrays and Strings

C Pointers 2013 Author Riko H i

Ch. 12: Operator Overloading

CS313D: ADVANCED PROGRAMMING LANGUAGE

Language Reference Manual simplicity

How to approach a computational problem

The New C Standard (Excerpted material)

School of Computer Science CPS109 Course Notes 5 Alexander Ferworn Updated Fall 15

2.2 Syntax Definition

Programming Languages Third Edition. Chapter 9 Control I Expressions and Statements

Zhifu Pei CSCI5448 Spring 2011 Prof. Kenneth M. Anderson

Will introduce various operators supported by C language Identify supported operations Present some of terms characterizing operators

CE221 Programming in C++ Part 1 Introduction

Assignment #5 Answers

Slide Set 14. for ENCM 339 Fall Steve Norman, PhD, PEng. Electrical & Computer Engineering Schulich School of Engineering University of Calgary

Introduction to C++ Introduction. Structure of a C++ Program. Structure of a C++ Program. C++ widely-used general-purpose programming language

LESSON 1. A C program is constructed as a sequence of characters. Among the characters that can be used in a program are:

register lock_guard(mtx_); string_view s = register to_string(42); We propose register-expression to grant the temporary objects scope lifetimes.

(Refer Slide Time: 1:40)

CSCI312 Principles of Programming Languages!

Type Checking in COOL (II) Lecture 10

Introduction to C++ with content from

COMSC-051 Java Programming Part 1. Part-Time Instructor: Joenil Mistal

(5-1) Object-Oriented Programming (OOP) and C++ Instructor - Andrew S. O Fallon CptS 122 (February 4, 2019) Washington State University

Operating Systems CMPSCI 377, Lec 2 Intro to C/C++ Prashant Shenoy University of Massachusetts Amherst

nptr = new int; // assigns valid address_of_int value to nptr std::cin >> n; // assigns valid int value to n

CSCE 120: Learning To Code

COMP322 - Introduction to C++ Lecture 01 - Introduction

Chapter 1 Getting Started

CS93SI Handout 04 Spring 2006 Apr Review Answers

Programming Lecture 3

What we will do today Explain and look at examples of. Programs that examine data. Data types. Topic 4. variables. expressions. assignment statements

Floating Point. What can be represented in N bits? 0 to 2N-1. 9,349,398,989,787,762,244,859,087, x 1067

Exercise 1.1 Hello world

Software Engineering Concepts: Invariants Silently Written & Called Functions Simple Class Example

IS0020 Program Design and Software Tools Midterm, Fall, 2004

Transcription:

Proceedings of the South Dakota Academy of Science, Vol. 85 (2006) 107 THE EVALUATION OF OPERANDS AND ITS PROBLEMS IN C++ Dan Day and Steve Shum Computer Science Department Augustana College Sioux Falls, SD 57197 INTRODUCTION In beginning C++ courses, the precedence of operators is a main focus. It is taught that each operator has certain precedence. It is also said that mathematical operators are math-like in operation while the non-math operators just fit in the mix somewhere. More or less, these courses focus on how the operators work on the values of operands. However, this focus is not the whole story. All implementations have some method of evaluating operands in order to retrieve the values that they store. What is important is that C++ does not provide a strict ordering of when the operands are evaluated, unlike operator precedence. Many assume that the evaluation of operands will coincide with operator precedence, but this is not guaranteed. It is important to know that C++ leaves all ordering of evaluating operands unspecified and a certain subset of those evaluations involving side effects undefined. EVALUATING OPERANDS C++ is not strict about how an implementation evaluates operands (and side effects, which will be considered later). It allows for a lot of freedom. Here is the relevant section in the C++ standard: Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified. In general, the order of evaluating operands is unspecified. This means that there is no certain order an implementation must follow. For example, Java has a guarantee that all operands are evaluated in a left-to-right order. In C++, an implementation is free to evaluate operands in a left-to-right, right-to-left, or any other imagineable order. Moreover, an implementation does not have to be consistent with evaluating operands. It may order the operands of one expression different than the same, exact expressions that may appear later in the program. What does this all mean? Take this code for example:

108 Proceedings of the South Dakota Academy of Science, Vol. 85 (2006) int g() std::cout << g() << std::endl; return 0; int f() std::cout << f() << std::endl; return 0; return g() + f(); It is unknown at compile-time if the implementation will call function g or f first. Consequently, it is unknown whether which text will appear first on the screen. There are two possible ways an implementation could order the evaluation of operands, and both are equally available to the implementation. It must be noted that a definite output will occur. The program is well-formed, valid according to the C++ standard, so it must produce some type of output and not crash. This behavior must be contrasted with undefined behavior, which will be discussed shortly. SEQUENCE POINTS, SIDE EFFECTS, AND UNDEFINED BEHAVIOR Side Effects and Sequence Points As shown, all evaluation of operands is done in an unspecified way. However, there is a subset of evaluation that actually can produce undefined behavior. This situation arises when a programmer uses expressions that cause side effects to the operands. C++ defines side effects to be: Accessing an object designated by a volatile lvalue, modifying an object, calling a library I/O function, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment. Evaluation of an expression might produce side effects. In addition, C++ leaves the time of resolution of the side effect (being the actual point in the execution of the program where the side effect is actually applied) up to the implementation. All that C++ requires is that an implementation must resolve all side effects between two sequence points at some point no later than the next sequence point. A sequence point is:

Proceedings of the South Dakota Academy of Science, Vol. 85 (2006) 109 At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place. Sequence points are mostly found at semicolons, functions, and some operators. This is important because many operators do not have a sequence point; so many side effects can take place before an implementation must resolve the side effects. Sequence points are only found at these places: There is a sequence point at the completion of evaluation of each full-expression. When calling a function (whether or not the function is inline), there is a sequence point after the evaluation of all function arguments (if any) which takes place before execution of any expressions or statements in the function body. There is also a sequence point after the copying of a returned value and before the execution of any expressions outside the function. Several contexts in C++ cause evaluation of a function call, even though no corresponding function call syntax appears in the translation unit. The sequence points at function-entry and function-exit (as described above) are features of the function calls as evaluated, whatever the syntax of the expression that calls the function might be. In the evaluation of each of the expressions a && b a b a? b : c a, b using the built-in meaning of the operators in these expressions, there is a sequence point after the evaluation of the first expression. The importance of sequence points relates to what a programmer can and cannot do between sequence points. While C++ is very loose towards the implementation, C++ requires programmers to realize that there are certain rules of how many side effects a programmer can apply to a single operand. THE PROBLEM WITH SEQUENCE POINTS A problem arising sequence points is that an operand can have multiple side effects between any two sequence points. Consider this piece of code: int i = 0; i = 5 + i++; Within the second statement (since we are unconcerned with the declaration), there is only one sequence point, the semicolon, and two side effects, the assignment and increment operators. The problem is what is i after the semico-

110 Proceedings of the South Dakota Academy of Science, Vol. 85 (2006) lon: 5 or 1? Since an implementation can order side effects freely, a programmer would think either is possible. However, the above code actually produces undefined behavior. Undefined behavior simply means that a program is no longer well-formed and may produce any result, including crashing during execution. The fact that the code attempts to put multiple side effects on i between two sequence points is the cause of undefined behavior. Why is the above program undefined? It is because C++ only allows so many side effects on any one operand between sequence points. Here is the relevant section: Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined. A programmer must be careful about this rule. An operand can only be modified once between sequence points, although its value can be accessed multiple times. It is important to realize the seriousness of this rule. Breaking in this rule can easily create a program that is ill-formed making it not portable and potentially unusable. EVALUATION, SIDE EFFECTS, AND OPERATOR OVERLOADING The rules of evaluating operands are mostly inherited from C. Mostly when the topic of sequence points and undefined behavior is brought up; it is talked about in terms of using built-in types, such as ints, chars, and pointers. However, C++ adds operator overloading, so it is worthy to wonder how sequence points related to user-defined objects and operator overloading. Consider this example: class X public: X operator++(int); //Implementation omitted X& operator=(const X& other); ; X x; x = x++;

Proceedings of the South Dakota Academy of Science, Vol. 85 (2006) 111 With a built-in type, this would clearly be undefined behavior. However, the type is user-defined. It is necessary to consider the nature of operator overloading. The fact that programmers use the operators directly is a matter of convenience, but the compiler must translate the code to use the functions defined in the class in order for the program to work. Consider if main was re-written as follows: X x; x.operator=(x.operator++(0)); For this article, operator overloading is nothing more than just calling member functions of a class. A compiler would translate the original code to one that uses functions. The presence of functions adds several sequence points, one before the calling of each function and one after each function returns. The existence of many sequence points does not cause undefined behavior like if a built-in type would have been used instead. SUMMARY While the order of evaluation of operands is a very technical subject in the C++ language, it is nevertheless an important one. Its subtle rules can lead to unexpected behavior in a program. It is necessary for a programmer to remember that it is incorrect to assume any specific ordering of evaluating operands or to assume any specific resolution of side effects. Assuming anything outside of the very loose rules C++ provides can lead to potential problems later during the development and porting of a software application. REFERENCES INTERNATIONAL STANDARD, ISO/IEC14882. Programming languages C++. 10/15/2003