A Simple C++ Quiz

Filed in C++ | Quizzes 1 Comment

Recently some people have been pestering me to post back up my C++ quizzes. So…without further ado here is the first one. The answers will be posted later.

  1. Given the following three lines of code, answer these questions
    int* p = new int[10];
    int* j = p + 11;
    int* k = p + 10;
    1. Is the second line well defined behavior?
    2. If the second line is well defined, where does the pointer point to?
    3. What are some of the legal operations that can be performed on the third pointer?
  2. What output should the following lines of code produce?
    int a = 10;
    std::cout<<a<<a++<<--a;
  3. Assuming the function called in the following block of code has no default parameters, and that no operators are overloaded, how many parameters does it take? Which objects are passed to it?
    f((a, b, c), d, e, ((g, h), i));
  4. Assuming the function called in the following block of code takes an A* and a B*, what is potentially wrong with the code?
    f(new A(), new B());

C++ Quiz #2

Filed in C++ | Quizzes 1 Comment

This is a test of your knowledge of C++, not of your compiler’s knowledge of C++. Using a compiler during this test will likely give you the wrong answers, or at least incomplete ones.

1. Using the code below as a reference, explain what behavior should be expected of each of the commented lines, please keep your answer very short.

struct Base {
	virtual void Arr();
};
struct SubBase1 : virtual Base {
};
struct SubBase2 : virtual Base {
	SubBase2(Base*, SubBase1*);
	virtual void Arr();
};
struct Derived : SubBase1, SubBase2 {
	Derived() : SubBase2((SubBase1*)this, this) {
	}
};

SubBase2::SubBase2(Base* a, SubBase1* b) {
	typeid(*a);                 //1
	dynamic_cast(a); //2
	typeid(*b);                 //3
	dynamic_cast(b); //4
	a->Arr();                   //5
	b->Arr();                   //6
}

2. Using the code below as a reference, explain what behavior should be expected of each of the commented lines?

template class X {
	X* p;  //1
	X a;  //2
};

C++ Quiz #3

Filed in C++ | Quizzes 1 Comment

This is a test of your knowledge of C++, not of your compiler’s knowledge of C++. Using a compiler during this test will likely give you the wrong answers, or at least incomplete ones.

Given the following code:

class Base {
public:
	virtual ~Base() {}
	virtual void DoSomething() {}
	void Mutate();
};

class Derived : public Base {
public:
	virtual void DoSomething() {}
};

void Base::Mutate() {
	new (this) Derived; // 1
}
void f() {
	void* v = ::operator new(sizeof(Base) + sizeof(Derived));
	Base* p = new (v) Base();
	p->DoSomething(); // 2
	p->Mutate();      // 3
	void* vp = p;     // 4
	p->DoSomething(); // 5
}

1. Does the first numbered line result in defined behavior? (Yes/No)
2. What should the first numbered line do?
3. Do the second and third numbered lines produce defined behavior? (Yes/No)
4. Does the fourth numbered line produce defined behavior? If so, why? If not, why?
5. Does the fifth numbered line produce defined behavior? If so, why? If not, why?

6. What is the behavior of calling void exit(int);?

Given the following code:

struct T{};
struct B {
	~B();
};

void h() {
	B b;
	new (&b) T; // 1
	return;     // 2
}

7. Does the first numbered line result in defined behavior?
8. Is the behavior of the second line defined? If so, why? If not, why is the behavior not defined?

9. What is the behavior of int& p = *(int*)0;? Why does it have that behavior? Is this a null reference?

10. What is the behavior of p->I::~I(); if I is defined as typedef int I; and p is defined as I* p;?

C++ Quiz #4

Filed in C++ | Quizzes 1 Comment

This is a test of your knowledge of C++, not of your compiler’s knowledge of C++. Using a compiler during this test will likely give you the wrong answers, or at least incomplete ones.

1. What is the value of i after the first numbered line is evaluated?
2. What do you expect the second numbered line to print out?
3. What is the value of p->c after the third numbered line is evaluated?
4. What does the fourth numbered line print?

struct C;

void f(C* p);

struct C {
	int c;
	C() : c(1) {
		f(this);
	}
};

const C obj;
void f(C* p) {
	int i = obj.c << 2;             //1
	std::cout<< p->c <<std::endl;   //2
	p->c = i;                       //3
	std::cout<< obj.c << std::endl; //4
}

5. What should you expect the compiler to do on the first numbered line? Why?

6. What should you expect the value of j to be after the second numbered line is evaluated? Why?

struct X {
	operator int() {
		return 314159;
	}
};

struct Y {
	operator X() {
		return X();
	}
};

Y y;
int i = y;     //1
int j = X(y);  //2

7. What should you expect the compiler to do on the first and second numbered lines? Why?

struct Z {
	Z() {}
	explicit Z(int) {}
};

Z z1 = 1;                 //1
Z z2 = static_cast<Z>(1); //2

8. What should you expect the behavior of each of the numbered lines, irrespective of the other lines, to be?

struct Base {
	virtual ~Base() {}
};

struct Derived : Base {
	~Derived() {}
};

typedef Base Base2;
Derived d;
Base* p = &d;
void f() {
	d.Base::~Base();    //1
	p->~Base();         //2
	p->~Base2();        //3
	p->Base2::~Base();  //4
	p->Base2::~Base2(); //5
}

Is It Really A Bug For A Beginner To Be Using C-Strings In C++?

Filed in C++ Comments Off

Depends, but probably yes.

A beginning programmer should be focusing on learning to program. That is: the process of taking a concept and turning it into an application. Problem solving, in other words. Learning to program is not the same thing as learning a programming language. Learning a programming language is about learning the syntax and standard library that comes with said programming language, it may involve the process of problem solving, but that is not its primary concern.

Given that, one can quickly see that the best way to introduce a beginning programmer to programming is to get them to use a language that is quick and easy to get up and running in. There are many languages that are quick and easy to get up and running in, and they all tend to share a rather similar component… which is verbosity. Python and Ruby are two prime examples, both of which have a very simple language syntax which allows for a lot of leeway for the programmer, without all the extra clutter that many other languages have (C++ *cough*). Another good choice, in my opinion, is C# which, when combined with Microsoft Visual C#, provides a very robust but easy to learn language. These languages all have many key features which make them easy to learn and use: All of them are generally garbage collected, they all have fairly simple syntax with few (if any) corner cases, and all of them have huge standard libraries that provide for a great deal of quick and easy to use functionality with minimal programmer effort.

C++ has almost none of those things. While there is Visual Studio for it, the IntelliSense is still not perfect, even with the help of tools like WholeTomato’s VAX. The standard library is quite small, dealing mainly with file and console IO, and some minimal containers. It leaves the rest of the work up to the developer. This means that for any sufficiently complex project you will either end up implementing a majority of the behaviors needed yourself, or having to dig up third party libraries and APIs for said behavior. Even the recent C++0x work hasn’t really alleviated the problem. Then you have the language complexity of which I’ve commented on previously

However, the C++ standard library does provide some features that should be in every developers pocketbook… such as std::string. std::string behaves a lot more like what a beginning programmer expects a primitive type to work. They’ve learned that you can add integers and floats together, so why can’t they add strings together? Well, with std::string they can, but with c-strings they can’t. They’ve learned to compare integers and floats using the standard == operator, so why can’t they do that with strings? With std::string they can, but with c-strings they can’t (well, they “can”, but the behavior is not what they want). They’ve learned how to read in integers and floats from std::cin, so why can’t they do the same with strings? They can with std::string, but with c-strings they have to be careful of the length and also that they’ve pre-allocated it, which has hazards of its own… such as stack space issues when they try to create a char array of 5000 characters.

C-strings do not behave intuitively. They have no inherit length, instead preferring to use null terminators to indicate the end of the string. They cannot be trivially concatenated, instead requiring the user to ensure that appropriate space is available, and then they have to use various function calls to copy the string, and then they have to ensure that those string functions had the space required to copy the null terminator (which the strncpy and other functions MAY omit if there isn’t enough space in the destination). Comparison requires the use functionality like strcmp, which doesn’t return true/false, but instead returns an integer indicating the string difference, with 0 being no differences. In a language where the user has been taught that 0/null generally means failure, remembering to test for 0 in that one off corner case is rather strange.

For a beginner, all that strangeness doesn’t equate to extra power or better performance. Instead it equates to extra confusion, and strange crashes. Had they been taught std::string first, they would have been free and clear, able to use the familiar operators they are used to, while being safe and secure in the bosom that is std::string. In fact, it generally gets worst than that, as c-strings are usually taught before pointers! This makes it even more confusing for the poor beginner, because then they’re introduced to arrays and pointers (instead of say std::vector), and now have a whole slew of new functionality to basically kill themselves with.

Thus, in conclusion, if you see a c-string in a beginners code, it probably means they have a bug somewhere in their code.

, ,

TOP