gcc stack.c rpn.c
printf("Enter format string: ");
char format[200]; /* be safe? */
scanf("%s", format); /* scan reads from stdin */
printf(format, name, age);
makefile
string-struct.c
#include <string.h>
char first[40], last[40];
...
cout << "Length of " << first << ": " << strlen(first);
// first becomes last:
strcpy(first, last);
// check if they are ordered
if ( strcmp(first, last) < 0 )
cout << first << " before " << last << endl;
int strlen(const char str[]) // const: won't change array contents
{
int len = 0;
while ( str[len] != '\0' )
++len;
return len;
}
strcpy(animal, "giraffe");
char name[] = "Elizabeth";
strcpy(name, name + 2); // ALSO unsafe - never overlap the strings on these
name[0] = NULL; // or, name[0] = '\0';
Any characters after the NULL don't matter. After
this, strlen(name) returns 0.
const int LEN = 10;
char word[LEN];
printf("Enter word: ");
scanf("%s", word); // trusting user!
word[LEN - 1] = '\0'; // but not completely...
if ( word[0] != '\0' ) // at least one char
{
char last = word[strlen(word) - 1];
if ( last != 's' && last != 'S' ) {
word[LEN - 2] = '\0'; // ensure space...
strcat(word, "s"); // no need to use strncat
}
}
struct X {int a;};, X
something; is illegal in C but legal in C++
struct: they use the C++17
standard, so their examples compile as C++ code but not as C code
typedef struct
{
char name[100];
int id;
int term_hours, cum_hours;
float term_gp, cum_gp;
} Student;
Student grace;
strcpy(grace.name, "Grace Hopper");
grace.id = 101;
grace.term_hours = 14;
grace.cum_hours = 110;
grace.term_gp = 49.2;
grace.cum_gp = 385.0;
This gives the memory map
| grace | ||||||||
|
|
Student *new = malloc(sizeof(Student));
new->term_gp = new->cum_gp = 0.0;
strcpy(new->name, "Help?");
sizeof(Student) - the compiler may organize
data differently than what you expect, and this is the only robust way to
determine its size
#define NAMELEN 100
typedef struct
{
char name[NAMELEN];
int id;
int term_hours, cum_hours;
float term_gp, cum_gp;
} Student;
#define for named constants later
new is a keyword in C++, not C
malloc is just a function call
malloc in C++, except
free on something created
with new or delete on something created
using malloc
void print_gpa(Student stu)
{
printf("%.4g", (double)stu.cum_gp / (double)stu.cum_hours);
}
print_gpa(grace);
print_gpa(*new);
void print_gpa(const Student *stu)
{
double gpa = (double)stu->cum_gp / (double)stu->cum_hours;
printf("%.4g", gpa);
}
print_gpa(&grace);
print_gpa(new);
typedef struct
{
int x, y;
} Point;
typedef struct
{
Point a, b;
} Line;
Line image[MAXLINES];
printf("%d", image[9].a.x);
void DrawImage(const Line image[], int numLines)
{
for(int i = 0; i < numLines; i++)
{
MoveTo(image[i].a.x, image[i].a.y);
LineTo(image[i].b.x, image[i].b.y);
}
}
sizeof
#include <stdbool.h>
struct Course {
char program[4];
int number;
bool full;
int seats_available;
float credits;
};
printf("Size of Course is %d\n", sizeof(Course));
sizeof(int) == sizeof(float) == 4
sizeof(bool) is technically not defined, but assume it
takes one byte in this context
sizeof would return 20
sizeof could return 48 or even be rounded up to 64
sizeof computed by compiler to be optimal
struct Course c;
c.seats_available = 25;
seats_available
gcc array.c
double underlying_data[7];
double *numbers = &underlying_data[3];
... numbers[-1] = ...
... numbers[3] = ... // (legal values from -3 to +3)
| 0 | 1 | 2 | 3 | 4 | 5 | |
|---|---|---|---|---|---|---|
| 0 | ||||||
| 1 | ||||||
| 2 | ||||||
| … | ||||||
| 9 |
#define X Y
all occurrances of X (case-sensitive) are replaced by Y
#define MAX_LEN 50
so
int nums[MAX_LEN];
translates to
int nums[50];
#define MAX_LEN 50;
int nums[MAX_LEN];
translates to
int nums[50;];
which won't compile
#define MAX_STRING_LENGTH 100
#define MAX_DECLARED_STRING MAX_STRING_LENGTH + 1
char name[MAX_DECLARED_STRING]; /* but see discussion below */
#define max(a, b) a > b ? a : b
#define sqr(x) x * x
#define name value
#define name(arguments) value
double y = max(u, v);
i = sqr(j);
translates to
double y = u > v ? u : v;
i = j * j;
i / j * j;
which is equivalent to (i / j) * j; should write:
#define sqr(x) (x * x)
#define sqr(x) ((x) * (x))
x at end: 7; y: 49
x at end: 7; y: 42
x++ + ++x would slow down lots of
reasonable code
#define assert(test) ((test) ? cerr \
: (cerr << "Assertion failure on line " \
<< __LINE__ << " of " << __FILE__ \
<< ": " << #test << endl))
assert(x > 0);
gives
((x > 0) ? cerr : (cerr << "Assertion failure on line "
<< 25 << " of " << "prog3.cpp"
<< ": " << "x > 0" << endl));
#ifdef _Windows cout << "This is compiled for Microsoft Windows." << endl; #else cout << "This is compiled for a non-Microsoft Windows system." << endl; #endif
#if 0
... errant code ...
#endif
// comment out following for release builds
#define DEBUG
...
#ifdef DEBUG
...
#endif
//
// util.h: utilities
//
#ifndef _util_h
#define _util_h
declarations, etc.
#endif
union Message
{
char text[1000];
float xs[200];
} msg;
strcpy(msg.text, "Hello, World");
msg.xs[0] = 3243.5234e12; msg.xs[1] = -1e5;
printf("%s", msg.text);
struct Message
{
enum { TEXT, DATA } message_type;
union MessageContents
{
char text[1000];
float xs[200];
} contents;
} msg;
...
if ( msg.message_type == TEXT )
display(msg.contents.text);
else
print_table(msg.contents.xs);
std::string optimization: can store short strings in
the pointer to the buffer; pseudocode for this, assuming the least
significant byte of a pointer overlaps to the last byte in an array
of characters:
union StringContent
{
char *bufp;
char contents[sizeof(char*)];
};
class string {
private:
StringContent text;
int len;
public:
// (bitwise operations would require casts in the following)
string(const char *src) : len(strlen(src) {
if ( len ≥ sizeof(char*) ) {
text.bufp = new char[len + 1];
strcpy(text.bufp, src);
text.bufp |= 0x01; // set low order bit as flag
} else {
text.bufp = 0; // fast way to clear all bits
strcpy(text.contents, src);
// note low order bit is 0 in this case (no matter src len)
}
}
char* c_str() {
if ( text.bufp & 0x01 )
return text.bufp & ~(0x01); // clears low order bit
else
return &text.contents[0];
}
...
};
typedef long my_type;
long a = 5;
my_type b = a; // ok!
typedef double meters;
typedef double kilograms;
meters m;
...
kilograms k = m; // legal
struct Stack {
int data[100];
int count;
};
struct Set {
int data[100];
int count;
};
...
struct Stack a, b;
...
a = b; // ok!
...
struct Set x;
x = a; // illegal!
typdef struct {
int data[100];
int count;
} Stack100;
creates an anonymous struct that's distinct from Set, Stack.