Struct Properties The C struct mechanism is vaguely similar to the Java/C++ class mechanisms: - supports the creation of user-defined data types - struct.

Slides:



Advertisements
Similar presentations
Object Oriented Programming COP3330 / CGS5409.  C++ Automatics ◦ Copy constructor () ◦ Assignment operator =  Shallow copy vs. Deep copy  DMA Review.
Advertisements

ECE 353: Lab C Pointers and Structs. Basics A pointer holds an address to some variable Notation: – Dereferencing operator: * int *x is a declaration.
6/10/2015C++ for Java Programmers1 Pointers and References Timothy Budd.
Rossella Lau Lecture 8, DCO10105, Semester B, DCO10105 Object-Oriented Programming and Design  Lecture 8: Polymorphism & C++ pointer  Inheritance.
ARRAYS AND POINTERS Although pointer types are not integer types, some integer arithmetic operators can be applied to pointers. The affect of this arithmetic.
Pointers Applications
11 Values and References Chapter Objectives You will be able to: Describe and compare value types and reference types. Write programs that use variables.
Chapter 13: Pointers, Classes, Virtual Functions, and Abstract Classes
 2006 Pearson Education, Inc. All rights reserved Classes: A Deeper Look.
C++ Programming: Program Design Including Data Structures, Fourth Edition Chapter 13: Pointers, Classes, Virtual Functions, and Abstract Classes.
Pointer Data Type and Pointer Variables
Data Structures Using C++ 2E Chapter 3 Pointers and Array-Based Lists.
C++ Programming: From Problem Analysis to Program Design, Fourth Edition Chapter 14: Pointers, Classes, Virtual Functions, and Abstract Classes.
EE4E. C++ Programming Lecture 1 From C to C++. Contents Introduction Introduction Variables Variables Pointers and references Pointers and references.
Overloading Binary Operators Two ways to overload –As a member function of a class –As a friend function As member functions –General syntax Data Structures.
Case Study - Fractions Timothy Budd Oregon State University.
Data Structures Using C++ 2E Chapter 3 Pointers. Data Structures Using C++ 2E2 Objectives Learn about the pointer data type and pointer variables Explore.
Pointer and Array Lists Chapter 3, Summary CS 244 Brent M. Dingle, Ph.D. Game Design and Development Program Department of Mathematics, Statistics, and.
Chapter 12: Pointers, Classes, Virtual Functions, and Abstract Classes.
CS 376b Introduction to Computer Vision 01 / 23 / 2008 Instructor: Michael Eckmann.
Nyhoff, ADTs, Data Structures and Problem Solving with C++, Second Edition, © 2005 Pearson Education, Inc. All rights reserved Stacks.
CPSC 252 The Big Three Page 1 The “Big Three” Every class that has data members pointing to dynamically allocated memory must implement these three methods:
CS 261 – Data Structures Introduction to C Programming.
Pointers in C Computer Organization I 1 August 2009 © McQuain, Feng & Ribbens Memory and Addresses Memory is just a sequence of byte-sized.
Java & C++ Comparisons How important are classes and objects?? What mechanisms exist for input and output?? Are references and pointers the same thing??
MORE POINTERS Plus: Memory Allocation Heap versus Stack.
Structs in C Computer Organization I 1 November 2009 © McQuain, Feng & Ribbens struct Properties The C struct mechanism is vaguely similar.
Chapter 12: Pointers, Classes, Virtual Functions, Abstract Classes, and Lists.
C++ for Engineers and Scientists Second Edition Chapter 12 Pointers.
Memory Management.
Dynamic Allocation in C
A History Lesson Adapted from Chapter 1 in C++ for Java Programmers by Weiss and C for Java Programmers: a Primer by McDowell Development of language by.
Computer Organization and Design Pointers, Arrays and Strings in C
User-Written Functions
Struct Properties The C struct mechanism is vaguely similar to the Java/C++ class mechanisms: - supports the creation of user-defined data types - struct.
Struct Properties The C struct mechanism is vaguely similar to the Java/C++ class mechanisms: - supports the creation of user-defined data types - struct.
Chapter 13: Pointers, Classes, Virtual Functions, and Abstract Classes
Andy Wang Object Oriented Programming in C++ COP 3330
Introduction to the C programming language
struct Copy Operation In C, variables are copied in three situations:
Java Primer 1: Types, Classes and Operators
C Basics.
Java Review: Reference Types
Struct Properties The C struct mechanism is vaguely similar to the Java/C++ class mechanisms: - supports the creation of user-defined data types - struct.
Memory and Addresses Memory is just a sequence of byte-sized storage devices. The bytes are assigned numeric addresses, starting with zero, just like the.
Pointers and References
User-Defined Functions
This pointer, Dynamic memory allocation, Constructors and Destructor
Pointers and References
Chapter 12: Pointers, Classes, Virtual Functions, and Abstract Classes
Object Oriented Programming COP3330 / CGS5409
Chapter 15 Pointers, Dynamic Data, and Reference Types
Chapter 14: Pointers, Classes, Virtual Functions, and Abstract Classes
Pointers, Dynamic Data, and Reference Types
A History Lesson Adapted from Chapter 1 in C++ for Java Programmers by Weiss and C for Java Programmers: a Primer by McDowell Development of language by.
Advanced Program Design with C++
Chapter 15 Pointers, Dynamic Data, and Reference Types
Pointers C#, pointers can only be declared to hold the memory addresses of value types int i = 5; int *p; p = &i; *p = 10; // changes the value of i to.
Classes and Objects.
Classes, Constructors, etc., in C++
Dynamic Allocation in C
9-10 Classes: A Deeper Look.
Chapter 9 Introduction To Classes
Class rational part2.
Pointers and References
The Three Attributes of an Identifier
Functions Students should understand the concept and basic mechanics of the function call/return pattern from CS 1114/2114, but some will not. A function.
9-10 Classes: A Deeper Look.
SPL – PS3 C++ Classes.
SPL – PS2 C++ Memory Handling.
Presentation transcript:

struct Properties The C struct mechanism is vaguely similar to the Java/C++ class mechanisms: - supports the creation of user-defined data types - struct types encapsulate data members struct Location { int X, Y; }; But there are vital differences: - struct data members are "public", in fact there is no notion of access control - struct types cannot have function members - there is no concept of inheritance or of polymorphism

A struct Example Note: - assignment is supported for struct types struct Location { // declare type globally int X, Y; }; int main() { struct Location A; // declare variable of type Location A.X = 5; // set its data members A.Y = 6; struct Location B; // declare another Location variable B = A; // copy members of A into B return 0; } Note: - assignment is supported for struct types - type declaration syntax used here requires specific use of struct in instance declarations

Another struct Example struct _Location { // declare type globally int X, Y; }; typedef struct _Location Location; // alias a type name int main() { Location A; // declare variable of type Location A.X = 5; // set its data members A.Y = 6; Location B; // declare another Location variable B = A; // copy members of A into B return 0; } Note: - use of typedef creates an alias for the struct type - simplifies declaration of instances

struct Limitations What else is supported naturally for struct types? Not much… - no automatic support for equality comparisons (or other relational comparisons) - no automatic support for I/O of struct variables - no automatic support for deep copy - no automatic support for arithmetic operations, even if they make sense… - can pass struct variables as parameters (default is pass-by-copy of course) - can return a struct variable from a function - can implement other operations via user-defined (non-member) functions

A struct Function Example struct _Location { // declare type globally int X, Y; }; typedef struct _Location Location; // alias a type name void initLocation(Location* L, int x, int y) { (*L).X = x; // alternative: L->X = x; (*L).Y = y; } Location A; // call: initLocation(&A, 5, 6); Note: - must pass Location object by pointer so function can modify original copy - given a pointer to a struct variable, we access its members by dereferencing the pointer (to get its target) and then using the member selector operator '.' - the parentheses around the *L are necessary because * has lower precedence than . - however, we can write L->X instead of (*L).X. - use of address-of '&' operator in call to create pointer to A

Another struct Function Example struct _Location { // declare type globally int X, Y; }; typedef struct _Location Location; // alias a type name Location updateLocation(Location Old, Location Move) { Location Updated; // make a local Location object Updated.X = Old.X + Move.X; // compute its members Updated.Y = Old.Y + Move.Y; return Updated; // return copy of local object } Note: - we do not allocate Updated dynamically (via malloc); there is no need since we know at compile time how many we need (1) and we can just return a copy and avoid the cost of a dynamic allocation at runtime - in C, dynamic allocation should only be used when logically necessary

Typical struct Code Organization // header file Location.h contains declaration of type and // supporting functions #ifndef LOCATION_H #define LOCATION_H struct _Location { // declare type globally int X, Y; }; typedef struct _Location Location; // alias a clean type name Location updateLocation(Location Old, Location Move); . . . #endif // Source file Location.c contains implementations of supporting // functions #include "Location.h" Location updateLocation(Location Old, Location Move) { . . . }

More Complex struct Types // A struct type may contain array members, members of other // struct types, anything in fact: #ifndef QUADRILATERAL_H #define QUADRILATERAL_H #include "Location.h" #define NUMCORNERS 4 struct _Quadrilateral { Location Corners[NUMCORNERS]; }; typedef struct _Quadrilateral Quadrilateral; . . . #endif Note: - even though you cannot assign one array to another and you cannot return an array from a function, you can do both of those things with a struct variable that contains an array member - Why?

Example: Rational Numbers One shortcoming in C is the lack of a type to represent rational numbers. A rational number is the ratio of two integers, where the denominator is not allowed to be zero. Rational numbers are important because we cannot represent many such fractions exactly in decimal form (e.g., 1/3). The struct mechanism in C allows us to implement a type that accurately represents rational numbers (within the restrictions imposed by the limited range of integer types). The following slides are a case study based on a course project.

Designing Data Representation One fact is clear enough: a rational value consists of two integer values. The obvious C approach would be: struct _Rational { int32_t Top; int32_t Bottom; }; typedef struct _Rational Rational; A forward-looking approach might use int64_t instead, buying increased range and doubling the storage cost. Another thought would be to normalize the representation by using a uint32_t for the denominator, so that a negative rational would always use a negative numerator. For this example, we'll stick with the C code shown above.

Designing Operations When implementing a data type, we must consider what operations would be expected or useful to potential users. In this case, we have mathematics as a guide: - creating a Rational object with any valid value - adding two Rational objects to yield a third Rational object - subtracting two Rational objects to yield a third Rational object - multiplying two Rational objects to yield a third Rational object - dividing two Rational objects to yield a third Rational object - taking the absolute value of a Rational object, yielding a second Rational object - negating a Rational object, yielding a second Rational object - comparing two Rational objects, with equals, less-than, etc. - taking the floor/ceiling of a Rational object, yielding an integer

A Specific Operation Rational First, Second; /** * Compute the sum of Left and Right. * Pre: * *Left and *Right have been properly initialized. * Returns: * A pointer to a Rational object equal to *Left + *Right. */ Rational* Rational_Add(const Rational* Left, const Rational* Right) { Rational *Sum = malloc(sizeof(Rational)); Sum->Top = Left->Top * Right->Bottom + Left->Bottom * Right->Top; Sum->Bottom = Left->Bottom * Right->Bottom; Rational_Normalize(Sum); return Sum; } Rational First, Second; ... // initialize First and Second Rational *Sum = Rational_Add(&First, &Second);

A Different Take on That /** * Compute the sum of Left and Right. * Pre: * *pSum is a Rational object * Left and Right have been properly initialized. * Post: * *pSum is a normalized representation of Left + Right. */ void Rational_Add(Rational* const pSum, const Rational Left, const Rational Right) { pSum->Top = Left.Top * Right.Bottom + Left.Bottom * Right.Top; pSum->Bottom = Left.Bottom * Right.Bottom; Rational_Normalize(pSum); } Rational First, Second, Sum; ... // initialize First and Second Rational_Add(&Sum, First, Second);

An Array Type Alternatively, we could use an assert() in the parameter check: bool iArray_Init(…) { assert( pA != NULL); … Pro: users often ignore return values; an assert() cannot be ignored Con: should we waste code, and possibly time, checking preconditions on the parameters? One way to address (some of) the shortcomings in C arrays would be to implement: struct _iArray { int32_t* Data; uint32_t Dimension; uint32_t Usage; }; typedef struct _iArray iArray; bool iArray_Init(iArray* const pA, uint32_t Size) { if ( pA == NULL ) return false; pA->Data = calloc(Size, sizeof(int32_t)); if ( pA->Data == NULL ) { pA->Dimension = pA->Usage = 0; return false; } pA->Dimension = Size; pA->Usage = 0; return true;

Safe Array Insertion Mutator operations could now be implemented safely: bool iArray_Append(iArray* const pA, int32_t Elem) { if ( pA == NULL || pA->Dimension == pA->Usage) { return false; } pA->Data[Usage] = Elem; pA->Usage++; return true; Reject insertion if array is full Data[usage] is the first unused cell in the array

Or… Check whether array is full realloc() will: It's easy to envision a full implementation of the iArray type, with bound-safe accessors and mutators. This is, in some ways, superior to Java arrays; for instance, this tracks usage as well as dimension. bool iArray_Append(iArray* const pA, int32_t Elem) { if ( pA == NULL ) return false; if ( pA->Dimension == pA->Usage) { int32_t *temp = realloc(pA->Data, 2 * pA->Dimension); if ( pA->Data == NULL ) { return false; } pA->Data = temp; pA->Dimension = 2 * pA->Dimension; pA->Data[Usage] = Elem; pA->Usage++; return true; Check whether array is full realloc() will: Allocate new array or simply "grow" the old one Copy data from old array to new array, if necessary Deallocate old array, if necessary Return NULL if fails

Making a Deep Copy Assignment only copies the actual data members (fields) of a struct variable. This is referred to as a shallow copy, and it's not suitable if there is dynamically-allocated content. To make a full (deep) copy, we must write a suitable copy function: /** Makes a duplicate of an existing iArray object. * Pre: * pA points to a correctly-initialized iArray object * Post: * A new iArray object has been created such that: * - Data[] duplicates the content and dimension of * the original * - Usage and Dimension equal the original * - no memory is shared between the two iArray objects * Returns: * Pointer to the new iArray object; NULL if it could not * be created. */ iArray* iArray_Copy(iArray* const pA);

Making a Copy Create new iArray object Create array field iArray* iArray_Copy(iArray* const pA) { if ( pA == NULL ) return NULL; iArray pCpy = calloc(1, sizeof(iArray)); if ( pCpy == NULL ) return NULL; pCpy->Data = malloc(pA->Dimension * sizeof(int32_t)); if ( pCpy->Data == NULL ) { free( pCpy ); return NULL; } memcpy(pCpy->Data, pA->Data, pA->Usage); pCpy->Dimension = pA->Dimension; pCpy->Usage = pA->Usage; return pCpy; Create new iArray object Create array field Copy array elems Set static fields