Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C/C++ Rarer keywords - register, volatile, extern, explicit [closed]

Tags:

c++

c

Can you give me a quick runthrough of what these 4 keywords are used for and why?

I understand the basics that google would tell you on register and volatile, but would like to know a little more (just a practical overview). Extern and explicit confuse me a little as I've never found a reason to have to use them myself despite doing fairly low-level embedded systems code. Again, I can google but I'd prefer a quick, practical summary from an expert so it sticks in my mind.

like image 571
John Humphreys Avatar asked Jul 27 '11 23:07

John Humphreys


People also ask

Can volatile be registered?

The volatile qualifier is applied to a variable when we declare it. It is used to tell the compiler, that the value may change at any time. These are some properties of volatile. It cannot cache the variables in register.

What is extern volatile in c?

extern means the variable is defined for use somewhere outside the definition scope. For example it could be defined in header file and get used in . c file. volatile means that modification of that variable should be consistent to the external world.

What is C++ volatile?

volatile means two things − - The value of the variable may change without any code of yours changing it. Therefore whenever the compiler reads the value of the variable, it may not assume that it is the same as the last time it was read, or that it is the same as the last value stored, but it must be read again.

What is the use of volatile keyword in c?

The volatile keyword is intended to prevent the compiler from applying any optimizations on objects that can change in ways that cannot be determined by the compiler. Objects declared as volatile are omitted from optimization because their values can be changed by code outside the scope of current code at any time.


2 Answers

extern

extern is overloaded for several uses. For global variables, it means that it is declaring the variable, not defining it. This is useful for putting global variables in headers. If you put this in a header:

int someInteger;

Each .cpp file that includes that header would try to have its own someInteger. That will cause a linker error. By declaring it with extern, all you're saying is that there will be a someInteger somewhere in the code:

extern int someInteger;

Now, in a .cpp file, you can define int someInteger, so that there will be exactly one copy of it.

There is also extern "C", which is used for specifying that certain functions use C-linkage rules rather than C++. This is useful for interfacing with libraries and code compiled as C.

In C++0x, there will also be extern template declarations. These are the opposite of explicit template instantiation. When you do this:

template class std::vector<int>;

You're telling the compiler to instantiate this template right now. Normally, the instantiation is delayed until the first use of the template. In C++0x, you can say:

extern template class std::vector<int>;

This tells the compiler not to instantiate this template in this .cpp file, ever. That way, you can control where templates are instantiated. Judicious use of this can substantially improve compile times.

explicit

This is used to prevent automatic conversions of types. If you have a class ClassName with the following constructor:

ClassName(int someInteger);

This means that if you have a function that takes a ClassName, the user can call it with an int, and the conversion will be done automatically.

void SomeFunc(const ClassName &className);
SomeFunc(3);

That's legal, because ClassName has a conversion constructor that takes an integer. This is how functions that take std::string can also take a char*; std::string has a constructor that takes a char*.

However, most of the time you don't want implicit conversions like this. You only usually want conversions to be explicit. Yes, it's sometimes useful as with std::string, but you need a way to turn it off for conversions that are inappropriate. Enter explicit:

explicit ClassName(int someInteger);

This will prevent implicit conversions. You can still use SomeFunc(ClassName(3)); but SomeFunc(3) will no longer work.

BTW: if explicit is rare for you, then you're not using it nearly enough. You should use it at all times, unless you specifically want conversion. Which is not that often.

volatile

This prevents certain useful optimizations. Normally, if you have a variable, C/C++ will assume that it's contents will only change if it explicitly changes them. So if you declare a int someInteger; as a global variable, C/C++ compilers can cache the value locally and not constantly access the value every time you use it.

Sometimes, you want to stop this. In those cases, you use volatile; this prevents those optimizations.

register

This is just a hint. It tells the compiler to try to put the variable's data in a register. It's essentially unnecessary; compilers are better than you are at deciding what should and should not be a register.

like image 103
Nicol Bolas Avatar answered Nov 11 '22 16:11

Nicol Bolas


register used as a hint to the compiler that a variable should be stored in a register instead of on the stack. Compilers will frequently ignore this and do whatever they want; variables will be allocated into registers if at all possible anyway.

volatile indicates memory may change without the program actually doing anything. This is another hint to the compiler that it should avoid optimizing accesses to that location. For instance, if you have two consecutive writes to the same location with no intervening reads, the compiler might optimize away the first one. However, if the location you're writing to is a hardware register, you would need every write to go through, exactly as written. So volatile is like saying "just trust me on this".

extern indicates a definition occurs outside of the current file. Useful for global variables, but usually implied in a declaration anyway. As Blindy notes, it's also useful for indicating a function should have C linkage. A function with C linkage will get compiled using its actual name as its symbol in the output executable. C++ functions include more information, like the types of their arguments in their symbols. This is why overloading works in C++ but not in C.

explicit applies to C++ constructors. It means that the constructor should not be called implicitly. For example, say you have an Array class with a constructor that accepts an integer capacity. You don't want integer values being implicitly converted into Array objects just because there's an integer constructor.

like image 45
Jay Conrod Avatar answered Nov 11 '22 18:11

Jay Conrod