auto variable and register variable -- optimized the same? - c

I am reading APUE, and when I came to longjmp , the question came. Before optimization, both the auto variable and register variable store in memory, after optimization, they store in register, the book says. But when I use objdump -S a.out, I found both of them became to immediate operand. So ?

Your book was just simplifying. Even before optimizing there is no guarantee that variables are realized in memory. The difference between auto and register is just that you are not allowed to take the address of a register variable. The C compiler can do anything that behaves the same as the abstract machine.
That your compiler realizes these variables as immediats is an indication that the values that you have there are small and are compile time constants. So you probably could have declared them const or even as enum constants in the first place.

So the program is very simple, and the compilers have gotten much smarter since the book has been written.

So you used a different compiler, maybe on a different machine, probably with different levels of optimization, and you can conclude essentially nothing from this except that the behaviour of compilers varies, which makes it hard to write a text book that is accurate in every detail on all machines for all time.

Related

Does making a variable a const or final save bytes or memory?

I've been working with a program and I've been trying to conserve bytes and storage space.
I have many variables in my C program, but I wondered if I could reduce the program's size by making some of the variables that don't change throughout the program const or final.
So my questions are these:
Is there any byte save when identifying static variables as constant?
If bytes are saved by doing this, why are they saved? How does the program store the variable differently if it is constant, and why does this way need less storage space?
If bytes are not saved by defining variables as constant, then why would a developer define a variable this way in the first place? Could we not just leave out the const just in case we need to change the variable later (especially if there is no downfall in doing so)?
Are there only some IDEs/Languages that save bytes with constant variables?
Thanks for any help, it is greatly appreciated.
I presume you're working on deeply embedded system (like cortex-M processors).
For these, you know that SRAM is a scarce resource whereas you have plenty of FLASH memory.
Then as much as you can, use the const keyword for any variable that doesn't change. Doing this will tell compiler to store the variable in FLASH memory and not in SRAM.
For example, to store a text on your system you can do this:
const char* const txtMenuRoot[] = { "Hello, this is the root menu", "Another text" };
Then not only the text is stored in FLASH, but also its pointer.
All your questions depend heavily on compiler and environment. A C compiler intended for embedded environment can do a great job about saving memory, while others maybe not.
Is there any byte save when identifying static variables as constant?
Yes, it may be possible. But note that "const", generally, isn't intended to specify how to store a variable - instead its meaning is to help the programmer and the compiler to better understand the source code (when the compiler "understand better", it can produce better object code). Some compiler can use that information to also store the variable in read-only memory, or delete it and turn it into literals in object code. But in the context of your question, may be that a #define is more suitable.
If bytes are saved by doing this, why are they saved? How does the program store the variable differently if it is constant, and why does this way need less storage space?
Variables declared in source code can go to different places in the object code, and different places when an object file is loaded in memory and executed. Note that, again, there are differences on various architectures - for example in a small 8/16 bits MCU (cpu for electronic devices), generally there is no "loading" of an object file. So the value of a variable is stored somewhere - anyway. But at low level the compiler can use literals instead of addresses, and this mostly saves some memory. Suppose you declare a constant variable GAIN=5 in source code. When that variable is used in some formula, the compiler emits something like "LD R12,GAIN" (loads register R12 with the content of the address GAIN, where variable GAIN is stored). But the compiler can also emit "LD R12,#5" (loads the value "5" in R12). In both cases an instruction is needed, but in the second case there is no memory for variables involved. This is a saving, and can also be faster.
If bytes are not saved by defining variables as constant, then why would a developer define a variable this way in the first place? Could we not just leave out the const just in case we need to change the variable later (especially if there is no downfall in doing so)?
As told earlier, the "const" keyword is meant to better define what operations will be done on the variable. This is useful for programmers, for clarity. It is useful to clearly state that a variable is not intended to be modified, especially when the variable is a formal parameter. In some environments, there is actually some read-only memory that can only be read and not written to and, if a variable (maybe a "system variable") is marked as "const", all is clear to the programmer -and- the compiler, which can warn if it encounters code trying to modify that variable.
Are there only some IDEs/Languages that save bytes with constant variables?
Definitely yes. But don't talk about IDEs: they are only editors. And about languages, things are complicated: it depends entirely on implementation and optimization. Likely this kind of saving is used only in compilers (not interpreters), and depends a lot on optimization options/capabilities of the compiler.
Think of const this way (there is no such thing as final or constant in C, so I'll just ignore that). If it's possible for the compiler to save memory, it will (especially when you compile optimizing for size). const gives the compiler more information about the properties of an object. The compiler can make smarter decisions when it has more information and it doesn't prevent the compiler from making the exact same decision as before it had that information.
It can't hurt and may help and it also helps the programmers working with the code to easier reason about it. Both the compiler and the programmer are helped, no one gets hurt. It's a win-win.
Compilers can reduce the memory used based on the knowledge of the code, const help compiler to know the real code behaviour (if you activate warnings you can have suggestions of where to put const).
But a struct can contains unused byte due to alignment restrictions of the hw used and compilers cannot alter the inner order of a struct. This can be done only changing the code.
struct wide struct compact
{ {
int_least32_t i1; int_least32_t i1,
int_least8_t b; i2;
int_least32_t i2; int_least8_t b;
} }
Due to the alignment restrictions the struct wide can have an empty space between members 'b' and 'i2'.
This is not the case in struct compact because the elements are listed from the widest, which can require greater alignments, to the smaller.
In same cases the struct compact leads even to faster code.

How do 'C' statements execute inside memory

Suppose I have this piece of C code here:
int main() {
int a = 10;
printf("test1");
printf("test2");
someFunc();
a = 20;
printf("%d",a);
}
Well I think that all these statements are stored on the stack at a time and then popped one by one to get executed. Am I correct? If not, please correct me.
Not really no. The C standard doesn't mention a stack so your notions are ill-conceived.
A C compiler (or interpreter for that matter) can do anything it likes so long as it follows the C standard.
In your case, that could mean, among other things, (i) the removal of a altogether, since it's only used to output 20 at the end of the function, and (ii) someFunc() could be removed if there are no side effects in doing so.
What normally happens is that your code is converted to machine code suitable for the target architecture. These machine code instructions do tend to follow the code quite faithfully (C in this sense is quite "low level") although modern compilers will optimise aggressively.
The C standard doesn't specify where things go in memory.
However, computers work like this in general:
Your program consists of various memory sections/segments, usually they are called .data, .bss, .rodata, .stack, .text and there is possibly also a .heap. The .text section is for storing the actual program code, the rest of the sections are for storing variables. More info on Wikipedia.
The C code is translated to machine code (assembler) by the compiler. All code is stored inside the .text section, which is read-only memory.
Modern computers can "mark" memory as either code or data, and will be capable of generating hardware exceptions if you try to execute code in the data section, or treat the code section as data. This way the processor can assist in catching bugs like dangling pointers or run-away code.
In theory you could execute code from any memory section, even on the stack, but because of the previously mentioned feature, this is not typically done. Most often, it wouldn't make any sense to do so anyhow.
So for your specific code snippet, the only thing that is stored on the stack is the variable a. Or more likely, it is stored in a CPU register, for performance reasons.
The string literals "test1", "test2" and "%d" will be stored in the .rodata section.
The literal 20 could either be stored in the .rodata section, or more likely, merged into the code and therefore stored in .text together with the rest of the code.
The program counter determines which part of the code that is currently executed. The stack is not involved in that what-so-ever, it is only for storing data.
Whats worth noting is that the C standard does not mandate implementation. So as long as the output is correct according to the standard, the compiler is free to implement this as it choses.
What most likely happens for you is that the compiler translates this bit of C into assembler code which is then executed top to bottom.
a = 20;
Is most likely optimised out unless you use it somewhere else. Good compilers also throw a warning for you like:
Warning: Unused Variable a

Economizing on variable use

I am working on some (embedded) device, recently I just started thinking maybe to use less memory, in case stack size isn't that big.
I have long functions (unfortunately).
And inside I was thinking to save space in this way.
Imagine there is code
1. void f()
2. {
3. ...
4. char someArray[300];
5. char someOtherArray[300];
6. someFunc(someArray, someOtherArray);
7. ...
8. }
Now, imagine, someArray and someOtherArray are never used in f function beyond line: 6.
Would following save some stack space??
1. void f()
2. {
3. ...
4. {//added
5. char someArray[300];
6. char someOtherArray[300];
7. someFunc(someArray, someOtherArray);
8. }//added
9. ...
8. }
nb: removed second part of the question
For the compiler proper both are exactly the same and thus makes no difference. The preprocessor would replace all instances of TEXT1 with the string constant.
#define TEXT1 "SomeLongStringLiteral"
someFunc(TEXT1)
someOtherFunc(TEXT1)
After the preprocessor's job is done, the above snippet becomes
someFunc("SomeLongStringLiteral");
someOtherFunc("SomeLongStringLiteral");
Thus it makes no difference performance or memory-wise.
Aside: The reason #define TEXT1 "SomeLongStringLiteral" is done is to have a single place to change all instances of TEXT1s usage; but that's a convinience only for the programmer and has no effect on the produced output.
recently I just started thinking maybe to use less memory, in case stack size isn't that big.
Never micro optimise or prematurely optimise. In case the stack size isn't that big, you'll get to know it when you benchmark/measure it. Don't make any assumptions when you optimise; 99% of the times it'd be wrong.
I am working on some device
Really? Are you? I wouldn't have thought that.
Now, imagine, someArray and someOtherArray are never used in f function beyond line 6. Would following save some stack space?
On a good compiler, it wouldn't make a difference. By the standard, it isn't specified if it saves or not, it isn't even specified if there is a stack or not.
But on a not so good compiler, the one with the additional {} may be better. It is worth a test: compile it and look at the generated assembler code.
it seems my compiler doesn't allow me to do this (this is C), so never mind...
But it should so. What happens then? Maybe you are just confusing levels of {} ...
I'll ask another one here.
Would better be a separate question...
someFunc("SomeLongStringLiteral");
someOtherFunc("SomeLongStringLiteral");
vs.
someFunc(TEXT1)
someOtherFunc(TEXT1)
A #define is processed before any compilation step, so it makes absolutely no difference.
If it happens within the same compilation unit, the compiler will tie them together anyway. (At least, in this case. On an ATXmega, if you use PSTR("whatever") for having them in flash space only, each occurrence of them will be put into flash separately. But that's a completely different thing...)
Modern compilers should push stack variables before they are used, and pop them when they are no longer needed. The old thinking with { ... } marking the start and end of a stack push/pop should be rather obsolete by now.
Since 1999, C allows stack variables to be allocated anywhere and not just immediately after a {. C++ allowed this far earlier. Today, where the local variable is declared inside the scope has little to do with when it actually starts to exist in the machine code. And similarly, the } has little to do with when is ceases to exist.
So regarding adding extra { }, don't bother. It is premature optimization and only adds pointless clutter.
Regarding the #define it absolutely makes no difference in terms of efficiency. Macros are just text replacement.
Furthermore, from the generic point-of-view, data must always be allocated somewhere. Data used by a program cannot be allocated in thin air! That's a very common misunderstanding. For example, many people incorrectly believe that
int x = func();
if(x == something)
consumes more memory than
if(func() == something)
But both examples compile into identical machine code. The result of func must be stored somewhere, it cannot be stored in thin air. In the first example, the result is stored in a memory segment that the programmer may refer to as x.
In the second example, it is stored in the very same memory segment, taking up the same amount of space, for the same duration of program execution. The only difference is that the memory segment is anonymous and the programmer has no name for it. As far as the machine code is concerned, that doesn't matter, since no variable names exist in machine code.
And this would be why every professional C programmer needs to understand a certain amount of assembler. You cannot hope to ever do any kind of manual code optimization if you don't.
(Please don't ask two questions in one, this is really annoying since you get two types of answer for your two different questions.)
For your first question. Probably putting {} around the use of a variable will not help. The lifetime of automatic variables that are not VLA (see below) is not bound to the scope in which it is declared. So compilers may have a hard time in figuring out how the use of the stack may be optimized, and maybe don't do such an optimization at all. In your case this is most likely the case, since you are exporting pointers to your data to a function that is perhaps not visible, here. The compiler has no way to figure out if there is a valid use of the arrays later on in the code.
I see two ways to "force" the compiler into optimizing that space, functions or VLA. The first, functions is simple: instead of putting the block around the code, put it in a static function. Function calls are quite optimized on modern platforms, and here the compiler knows exactly how he may clear the stack at the end.
The second alternative in your case is a VLA, variable length array, if you compiler supports that c99 feature. Arrays that have a size that doesn't depend on a compile time constant have a special rule for their lifetime. That lifetime exactly ends at the end of the scope where they are defined. Even a const-qualified variable could be used for that:
{
size_t const len = 300;
char someArray[len];
char someOtherArray[len];
someFunc(someArray, someOtherArray);
}
At the end, on a given platform, you'd really have to inspect what assembler your compiler produces.

Concept of register variables(datatype:register) in C language?

I just to want to get an idea about how the register variables are handled in C program executables. ie in which location(or register) it exactly get stored in case of an embedded system and in a X86 machine(C program executable in a desktop PC)?
What about this view? (correct me if am wrong)
Suppose we have declared/initialized one variable inside a function as 'int' datatype. Normally it will go to the stack segment and it will be there in that section only at run time ,when the caller calls the callee containing the local variable. But if we declare above local variable as 'register int' then also it'll go to the stack segment. But on run time , the processor put that local variable from stack to its general purpose register locations(because of extra compiler inserted code due to 'register' keyword) and a fast access of the same from there.
That is the only difference between them is at run time access and there is no memory loading differences between them.
__Kanu
The register keyword in C (rarely ever seen anymore) is only a hint to the compiler that it may be useful to keep a variable in a register for faster access.
The compiler is free to ignore the hint, and optimize as it sees best.
Since modern compilers are much better than humans at understanding usage and speed, the register keyword is usually ignored by modern compilers, and in some cases, may actually slow down execution speed.
From K&R C:
A register variable advises the
compiler that the variable in question
will be heavily used. The idea is that
register variables are to be placed in
machine registers, which may result in
smaller & faster programs. But
compilers are free to ignore this
advice.
It is not possible to take the address of a register variable, regardless of whether the variable is actually placed in a register.
Hence,
register int x;
int *y = &x; // is illegal
So, you must weigh in the cons of not being able to get the address of the register variable.
In addition to crypto's answer (that has my vote) just see the name register for the keyword as a historical misnomer. It has not much to do with registers as you learn it in class e.g for the von Neumann processor model, but is just a hint to the compiler that this variable doesn't need an address.
On modern machines an addressless variable can be realized by different means (e.g an immediate assembler operator) or optimized away completely. Tagging a variable as register can be a useful optimization hint for the compiler and also a useful discipline for the programmer.
When a compiler takes its internal code and the backend turns it into machine/assembler for the target processor, it keeps track of the registers it is generating instructions for as it creates the code. When it needs to allocate a register to load or keep track of a variable if there is an unused working variable then it marks it as used and generates the instructions using that register. But if all the working registers have something in them then it will usually evict the contents of one of those registers somewhere, often ram for example global memory or the stack if that variable had a home. The compiler may or may not be smart about that decision and may evict a variable that is highly used. By using the register keyword, depending on the compiler, you may be able to influence that decision, it may choose to keep the register keyword variables in registers and evict non-register keyword variables to memory as needed.
which location(or register) it exactly get stored in case of an embedded system and in a > X86 machine(C program executable in a desktop PC)?
You don't know without opening up the assembly output, which will be liable to shift based on compiler choices. It's a good idea to check the assembly just for educational purposes.
If you need to read and write particular registers that precisely, you should write inline assembly or link in an assembly module.
Typically when using a standard C compiler for x86/amd64 (gcc, icc, cl), you can reasonably assume that the compiler will optimize sufficiently well for most purposes.
If, however, you are using a non-standard compiler, e.g., one cooked up for a new embedded system, it is a good idea to consider hand optimization. If the architecture is new, it might also be a good idea to consider hand optimization.

Why do we need to suggest a variable to be stored in register?

As I know that in C we could use the keyword "register" to suggest to the compiler that the variable should be stored in the CPU register. Isn't it true that all variables that involved in CPU instructions will be eventually stored in CPU registers for execution?
The register keyword is a way of telling the compiler that the variable is heavily used. It's true that values must usually be loaded temporarily into registers to perform calculations on them. The name comes from the idea that a compiler might keep the variable in a register for the entire duration that it is in scope, rather than only temporarily when it is being used in a calculation.
The keyword is obsolete for the purpose of optimisation, since modern compilers can determine when a variable is heavily used (and when it does not have its address taken) without help from the programmer.
You should not use that register keyword. It is an antique relic, maintained for backward compatibility. Most compilers will ignore it (by default).
There could be exceptions but they are very rare, consult your compiler manual.
Isn't it true that all variables that involved in CPU instructions will be eventually stored in CPU registers for execution?
Yes, that is true. But CPU registers are limited so variables are usually LOAD/STOREd from 'normal' memory and live in a register only briefly. The register keyword is (was) a way of indicating high priority variables that should occupy a register longer. Like the i in for(i = 0; ...).
In old times, compilers weren't that smart as they are today. It was a hint from the programmer to the compiler that this variable should be stored in a register to allow fast access/modification. Today, almost any decent compiler implements clever registers allocation algorithms that beats the mind of humans.
Most variables will be loaded into registers for a short while...as long as necessary to do what needs to be done with them. The register keyword hints that they should be kept there.
Compilers' optimization has gotten so much better, though, that the register keyword isn't very helpful. In fact, if your compiler respects it at all (and many don't), it could even mess you up (by tying the compiler's hands, making certain optimizations impossible). So it's a pretty bad idea these days.

Resources