Previous Lecture Lecture 4 Next Lecture

Lecture 4, Thu 04/09

Namespaces, Structs, Padding

Namespaces

A high-level scenario:

Example

// F1.h
#ifndef F1_H
#define F1_H
#include <iostream>
namespace CS_32_F1 {
	void someFunction() {
		std::cout << "F1.someFunction()" << std::endl;
	}
}
#endif
// F2.h
#ifndef F2_H
#define F2_H
#include <iostream>
namespace CS_32_F2 {
	void someFunction() {
		std::cout << "F2.someFunction()" << std::endl;
	}
}
#endif
#include "F1.h"
#include "F2.h"
int main() {
	using namespace CS_32_F1;
	someFunction(); // F1.someFunction()
	return 0;
}
# Makefile
CXX=g++

# note F1.h and F2.h are not required, but can list them
# to make sure the files exist.
main: main.o F1.h F2.h
	${CXX} -o main -std=c++11 main.o
clean:
	rm -f *.o main

Notes:

Global Namespace

Appending to existing namespaces

Example - Namespaces spanning multiple files

// F1.h
#ifndef F1_H
#define F1_H
#include <iostream>

namespace CS_32_F1 {
    class string {
        public:
        void someFunction();
    };
}
#endif
// F2.h
#ifndef F2_H
#define F2_H
#include <iostream>

namespace CS_32_F2 {
    class string {
        public:
        void someFunction();
    };
}
#endif
// F1.cpp
#include <iostream>
#include "F1.h"

using namespace std;

namespace CS_32_F1 {
	void string::someFunction() {
		cout << "F1.someFunction()" << endl;
	}
}
// F2.cpp
#include <iostream>
#include "F2.h"

using namespace std;

namespace CS_32_F2 {
	void string::someFunction() {
		cout << "F2.someFunction()" << endl;
	}
}
// main.cpp
#include "F1.h"
#include "F2.h"

int main() {
	CS_32_F2::string x;
	x.someFunction(); // prints “F2.someFunction()”
	return 0;
}
# Makefile

CXX=g++

main: main.o F1.o F2.o
	${CXX} -o main -std=c++11 main.o F1.o F2.o

clean:
	rm -f *.o main

Specifying something in the global namespace.

Example

// main.cpp
using namespace CS_32_F1;

void someFunction() {
	cout << "in some function (global namespace)" << endl;
}

int main() {
	// someFunction(); // which one?? – won’t compile.
	::someFunction(); // knows it’s someFunction in global namespace
}

Structs

Memory Organization of Classes / Structs

Memory Padding

Example

#include <iostream>

using namespace std;

struct X {
    int a;      // 4 bytes
    short b;    // 2
    char c;     // 1
    char d;     // 1
};

int main() {
    X x;
    cout << sizeof(x) << endl;                                  // 8
    cout << "&x = " << &x << endl;                              // 0x7ffee6a167c8
    cout << "&x.a = " << &x.a << endl;                          // 0x7ffee6a167c8
    cout << "&x.b = " << &x.b << endl;                          // 0x7ffee6a167cc
    cout << "&x.c = " << reinterpret_cast<void*>(&x.c) << endl; // 0x7ffee6a167ce
    cout << "&x.d = " << reinterpret_cast<void*>(&x.d) << endl; // 0x7ffee6a167cf
}

Struct X:

Padding X

struct Y {
	char a;     // 1 byte
	int b;      // 4
	char c;     // 1
	short d;    // 2
};

int main() {
    Y y;
    cout << sizeof(y) << endl;                                  // 12
    cout << "&y = " << &y << endl;                              // 0x7ffeed3d4768
    cout << "&y.a = " << reinterpret_cast<void*>(&y.a) << endl; // 0x7ffeed3d4768
    cout << "&y.b = " << &y.b << endl;                          // 0x7ffeed3d476c
    cout << "&y.c = " << reinterpret_cast<void*>(&y.c) << endl; // 0x7ffeed3d4770
    cout << "&y.d = " << &y.d << endl;                          // 0x7ffeed3d4772
}

Struct Y:

Padding Y

struct Z {
    char a;     // 1 byte
    int b;      // 4
    char c;     // 1
    double d;   // 8
};

int main() {
    Z z;
    cout << sizeof(z) << endl;                                  // 24
    cout << "&z = " << &z << endl;                              // 0x7ffee07c1700
    cout << "&z.a = " << reinterpret_cast<void*>(&z.a) << endl; // 0x7ffee07c1700
    cout << "&z.b = " << &z.b << endl;                          // 0x7ffee07c1704
    cout << "&z.c = " << reinterpret_cast<void*>(&z.c) << endl; // 0x7ffee07c1708
    cout << "&z.d = " << &z.d << endl;                          // 0x7ffee07c1710
}

Struct Z:

Padding Z

class A {
    public:
    	char a;     // 1 byte
};

int main() {
    A a;
    cout << sizeof(a) << endl; // 1 byte
}

If we want to play more when checking different allocations:

#include <iostream>

using namespace std;

class X {
    public:
		int a;      
		short b;    
		int c;     
		char d;     
		
		void printSizes(){
			cout << sizeof(*this) << endl;	// size of the class
			cout << sizeof(a) << endl;
			cout << sizeof(b) << endl;
			cout << sizeof(c) << endl;
			cout << sizeof(d) << endl;			
		};

		void printAddresses(){
			cout << &(*this) << endl;	//address of the class
			
			cout << reinterpret_cast<void*>(&a) << endl;
			cout << reinterpret_cast<void*>(&b) << endl;
			cout << reinterpret_cast<void*>(&c) << endl;
			cout << reinterpret_cast<void*>(&d) << endl;			
		};
};

int main() {
	X x;
	x.printSizes();
	x.printAddresses();
}

https://www.geeksforgeeks.org/structure-member-alignment-padding-and-data-packing/