What does the register
keyword do in C language? I have read that it is used for optimizing but is not clearly defined in any standard. Is it still relevant and if so, when would you use it?

- 3,740
- 1
- 17
- 28

- 15,244
- 11
- 66
- 92
-
56*What does the register keyword do in C?* gets ignored :) – bestsss Feb 25 '11 at 16:50
-
27@bestsss Not completely ignored. Try to get an address of `register` variable. – qrdl Jun 14 '12 at 11:58
-
5That code you're reading is *old* https://www.youtube.com/watch?v=ibF36Yyeehw#t=1827 – Colonel Panic Dec 23 '14 at 16:03
19 Answers
It's a hint to the compiler that the variable will be heavily used and that you recommend it be kept in a processor register if possible.
Most modern compilers do that automatically, and are better at picking them than us humans.

- 14,451
- 16
- 82
- 145

- 20,639
- 15
- 57
- 92
-
22Well, I experimented with register to get my ACM submissions tweaked, and sometimes it really helped. But you really have to be carful, because poor choices degrade performance. – ypnos Feb 23 '09 at 16:20
-
92A good reason _not_ to use 'register': you can't take the address of a variable declared 'register' – Adam Rosenfield Feb 23 '09 at 16:21
-
27Note that some/many compilers will completely ignore the register keyword (which is perfectly legal). – Euro Micelli Feb 23 '09 at 17:49
-
6ypnos: Actually the speed of a solution for ACM ICPC problems depends much more on the algorithm choice than on such micro-optimizations. The 5-second time limit is usually enough for a correct solution, especially when using C instead of Java. – Joey Oct 15 '09 at 13:12
-
Also note that the effect of "register" (if the compiler chooses to respect it) will vary a lot between processor architectures and models. So even if "register" makes your program faster on your Pentium IV, it may make it slower on a Xeon, or an AMD processor, or a Sparc... . So it's really more like a last-ditch optimization. – sleske Jan 19 '10 at 12:39
-
74@Euro: You probably know this, but just to be explicit, the compiler is required to prevent the address of a `register` variable from being taken; this is the *only* mandatory effect of the `register` keyword. Even this is sufficient to improve optimizations, because it becomes trivial to tell that the variable can only be modified within this function. – Dale Hagglund Feb 09 '10 at 18:26
-
2It's still pretty useful in embedded. Decent compilers for embedded systems even allow you to set which variable goes into which register. – vsz Jan 22 '14 at 17:31
-
1Modern compilers start by putting *all* scalar auto locals - in fact all distinct writes to such locals - plus basically all intermediate expressions - into separate 'virtual registers', and then set about working out how to map all those into actual registers and memory. So it's actually quite restrictive to tell the compiler to put a variable into a register. Some variables may vanish completely (like the one used as the temp in a swap). I know this answer is 6 years old but it's more definitely true now, I'm pretty sure most modern compilers basically ignore 'register' for code generation. – greggo Feb 21 '15 at 22:10
-
1@DaleHagglund (I know it's 4+ years later but) the flow analysis done by compilers includes detecting that situation regardless of the 'register' keyword, from the actual code. Also, if you *only* take the address of a variable in order to pass that address to an inline function, and that inline function only stores a value at that pointer, the compiler may be able to simplify that (given aliasing checks) to a direct assignment to the variable. So, it could still be in a register, even with & applied to it. But this construct is prohibited with 'register' keyword. – greggo Feb 21 '15 at 22:18
-
1@greggo: I understand that all modern compilers do the sort of analysis you describe, and that any scalar variable can end up in a register if it meets the right criteria. At least for me, the upshot of this is that I never use the register keyword anymore. It's a relic from the days when compilers weren't very good at intra-procedural dataflow analysis. – Dale Hagglund Feb 23 '15 at 02:44
I'm surprised that nobody mentioned that you cannot take an address of register variable, even if compiler decides to keep variable in memory rather than in register.
So using register
you win nothing (anyway compiler will decide for itself where to put the variable) and lose the &
operator - no reason to use it.
-
115There is a reason actually. The mere fact that you cannot take a address of the variable yields some optimization opportunities: the compiler can prove that the variable will not be aliased. – Alexandre C. Feb 09 '12 at 20:14
-
12Compilers are notoriously terrible at proving that aliasing doesn't occur in nontrivial cases, so `register` is useful for this even if the compiler doesn't put it in a register. – Miles Rout Jun 07 '14 at 05:33
-
2@AlexandreC , Miles, compilers are perfectly OK at checking whether & is taken of a variable anywhere. So regardless of other difficulties about detecting aliasing, restating that buys you nothing. When K+R first created C, it was indeed useful to know *in advance* that & would not be used, since that compiler actually made the register allocation decision on seeing the declaration, before looking at the following code. That is why the prohibition is in place. The 'register' keyword is essentially obsolete now. – greggo Feb 21 '15 at 22:31
-
37By this logic `const` is also be useless since it wins you nothing, you only loose the ability to change a variable. `register` could be used to make sure nobody takes the address of a variable in the future without thinking. I have never had reason to use `register` though. – Tor Klingberg Oct 29 '15 at 13:11
-
It tells the compiler to try to use a CPU register, instead of RAM, to store the variable. Registers are in the CPU and much faster to access than RAM. But it's only a suggestion to the compiler, and it may not follow through.

- 5,066
- 1
- 22
- 25
-
10Worth adding for people using C++, C++ lets you take the address of a register variable – Will Mar 30 '12 at 16:07
-
5@Will: ...but the compiler will likely end up ignoring the keyword as a result. See my answer. – bwDraco Dec 16 '12 at 23:03
-
Yes, it seems that 'register' is a placebo in C++, it's just there to allow C code to be compiled as C++. And it wouldn't make much sense to prohibit &var while allowing passing it by reference, or const-reference, and without pass-by-reference you've seriously broken C++. – greggo Feb 21 '15 at 22:23
-
1> "*without pass-by-reference you've seriously broken C++*" I did no such thing. It was like this when I first saw it ;) – user426 Nov 11 '21 at 01:43
I know this question is about C, but the same question for C++ was closed as a exact duplicate of this question. This answer therefore may not apply for C.
The latest draft of the C++11 standard, N3485, says this in 7.1.1/3:
A
register
specifier is a hint to the implementation that the variable so declared will be heavily used. [ note: The hint can be ignored and in most implementations it will be ignored if the address of the variable is taken. This use is deprecated ... —end note ]
In C++ (but not in C), the standard does not state that you can't take the address of a variable declared register
; however, because a variable stored in a CPU register throughout its lifetime does not have a memory location associated with it, attempting to take its address would be invalid, and the compiler will ignore the register
keyword to allow taking the address.

- 2,514
- 2
- 33
- 38
I have read that it is used for optimizing but is not clearly defined in any standard.
In fact it is clearly defined by the C standard. Quoting the N1570 draft section 6.7.1 paragraph 6 (other versions have the same wording):
A declaration of an identifier for an object with storage-class specifier
register
suggests that access to the object be as fast as possible. The extent to which such suggestions are effective is implementation-defined.
The unary &
operator may not be applied to an object defined with register
, and register
may not be used in an external declaration.
There are a few other (fairly obscure) rules that are specific to register
-qualified objects:
Defining an array object withregister
has undefined behavior.
Correction: It's legal to define an array object withregister
, but you can't do anything useful with such an object (indexing into an array requires taking the address of its initial element).- The
_Alignas
specifier (new in C11) may not be applied to such an object. - If the parameter name passed to the
va_start
macro isregister
-qualified, the behavior is undefined.
There may be a few others; download a draft of the standard and search for "register" if you're interested.
As the name implies, the original meaning of register
was to require an object to be stored in a CPU register. But with improvements in optimizing compilers, this has become less useful. Modern versions of the C standard don't refer to CPU registers, because they no longer (need to) assume that there is such a thing (there are architectures that don't use registers). The common wisdom is that applying register
to an object declaration is more likely to worsen the generated code, because it interferes with the compiler's own register allocation. There might still be a few cases where it's useful (say, if you really do know how often a variable will be accessed, and your knowledge is better than what a modern optimizing compiler can figure out).
The main tangible effect of register
is that it prevents any attempt to take an object's address. This isn't particularly useful as an optimization hint, since it can be applied only to local variables, and an optimizing compiler can see for itself that such an object's address isn't taken.

- 254,901
- 44
- 429
- 631
-
so is behaviour of [this](http://ideone.com/QIatqM) program really undefined according to C standard ? Is it well defined in C++ ? I think it is well defined in C++. – Destructor Jul 19 '16 at 16:16
-
@Destructor: Why would it be undefined? There's no `register`-qualified array object, if that's what you're thinking. – Keith Thompson Jul 19 '16 at 18:35
-
Oh sorry I forgot to write register keyword in array declaration in main(). Is it well defined in C++ ? – Destructor Jul 20 '16 at 06:21
-
I was wrong about defining `register` array objects; see the updated first bullet point in my answer. It's legal to define such an object, but you can't do anything with it. If you add `register` to the definition of `s` in [your example](http://ideone.com/QIatqM), the program is illegal (a constraint violation) in C. C++ doesn't place the same restrictions on `register`, so the program would be valid C++ (but using `register` would be pointless). – Keith Thompson Jul 20 '16 at 15:43
-
@KeithThompson: The `register` keyword could serve a useful purpose if it were legal to take the address of such a variable but only in cases where semantics would be unaffected by copying the variable to a temporary when its address is taken, and reloading it from the temporary at the next sequence point. That would allow compilers to assume that the variable may be safely kept in a register across all pointer accesses provided that it's flushed at any places its address is taken. – supercat Jul 20 '16 at 21:59
It hasn't been relevant for at least 15 years as optimizers make better decisions about this than you can. Even when it was relevant, it made a lot more sense on a CPU architecture with a lot of registers, like SPARC or M68000 than it did on Intel with its paucity of registers, most of which are reserved by the compiler for its own purposes.

- 179,021
- 58
- 319
- 408
-
Compiler are and remain pathetic at being better than the developer in identifying absence of aliasing and hence practices that reduce repeated indirection (very costly) and help cache data locally are very much relevant. – user426 Jun 07 '22 at 16:13
Actually, register tells the compiler that the variable does not alias with anything else in the program (not even char's).
That can be exploited by modern compilers in a variety of situations, and can help the compiler quite a bit in complex code - in simple code the compilers can figure this out on their own.
Otherwise, it serves no purpose and is not used for register allocation. It does not usually incur performance degradation to specify it, as long as your compiler is modern enough.

- 141
- 1
- 2
-
"tells the compiler.." no, it doesn't. All auto variables have that property, unless you take its address *and* use it in ways which exceed certain analyzable uses. So, the compiler knows this from the code, regardless of whether you use the register keyword. It so happens that the 'register' keyword makes it illegal to write such a construct, but if you don't use the keyword, and *dont* take the address in such a way, then the compiler still knows it's safe. Such information is crucial to optimization. – greggo Feb 21 '15 at 22:39
-
1@greggo: Too bad `register` forbids taking the address at all, since otherwise it could be useful to let compilers know of cases where a compiler would be able to apply register optimizations *despite* a variable's address being passed to an external function (the variable would have to be flushed to memory *for that particular call*, but once the function returns, the compiler could again treat it as a variable whose address had never been taken). – supercat May 26 '16 at 23:11
-
1@supercat I think would still be a very tricky conversation to have with the compiler. If that's what you want to tell the compiler, you can do it by copying the first variable to a second one which doesn't have '&' on it, and then never using the first one again. – greggo May 30 '16 at 19:38
-
1@greggo: Saying that if `bar` is a `register` variable, a compiler *may at its leisure* replace `foo(&bar);` with `int temp=bar; foo(&temp); bar=temp;`, but taking the address of `bar` would be forbidden in most other contexts would not seem like an overly complicated rule. If the variable could otherwise be kept in a register, the substitution would make code smaller. If the variable would need to be kept in RAM anyway, the substitution would make code bigger. Leaving the question of whether to make the substitution up to the compiler would lead to better code in both cases. – supercat May 31 '16 at 14:28
-
2@greggo: Allowing a `register` qualification on global variables, whether or not the compiler allows the address to be taken, would allow some nice optimizations in cases where an inlined function that use a global variable is called repeatedly in a loop. I can't think of any other way to let that variable be kept in a register between loop iterations--can you? – supercat May 31 '16 at 14:30
Storytime!
C, as a language, is an abstraction of a computer. It allows you to do things, in terms of what a computer does, that is manipulate memory, do math, print things, etc.
But C is only an abstraction. And ultimately, what it's extracting from you is Assembly language. Assembly is the language that a CPU reads, and if you use it, you do things in terms of the CPU. What does a CPU do? Basically, it reads from memory, does math, and writes to memory. The CPU doesn't just do math on numbers in memory. First, you have to move a number from memory to memory inside the CPU called a register. Once you're done doing whatever you need to do to this number, you can move it back to normal system memory. Why use system memory at all? Registers are limited in number. You only get about a hundred bytes in modern processors, and older popular processors were even more fantastically limited (The 6502 had 3 8-bit registers for your free use). So, your average math operation looks like:
load first number from memory
load second number from memory
add the two
store answer into memory
A lot of that is... not math. Those load and store operations can take up to half your processing time. C, being an abstraction of computers, freed the programmer the worry of using and juggling registers, and since the number and type vary between computers, C places the responsibility of register allocation solely on the compiler. With one exception.
When you declare a variable register
, you are telling the compiler "Yo, I intend for this variable to be used a lot and/or be short lived. If I were you, I'd try to keep it in a register." When the C standard says compilers don't have to actually do anything, that's because the C standard doesn't know what computer you're compiling for, and it might be like the 6502 above, where all 3 registers are needed just to operate, and there's no spare register to keep your number. However, when it says you can't take the address, that's because registers don't have addresses. They're the processor's hands. Since the compiler doesn't have to give you an address, and since it can't have an address at all ever, several optimizations are now open to the compiler. It could, say, keep the number in a register always. It doesn't have to worry about where it's stored in computer memory (beyond needing to get it back again). It could even pun it into another variable, give it to another processor, give it a changing location, etc.
tl;dr: Short-lived variables that do lots of math. Don't declare too many at once.

- 1,157
- 9
- 18
Just a little demo (without any real-world purpose) for comparison: when removing the register
keywords before each variable, this piece of code takes 3.41 seconds on my i7 (GCC), with register
the same code completes in 0.7 seconds.
#include <stdio.h>
int main(int argc, char** argv) {
register int numIterations = 20000;
register int i=0;
unsigned long val=0;
for (i; i<numIterations+1; i++)
{
register int j=0;
for (j;j<i;j++)
{
val=j+i;
}
}
printf("%d", val);
return 0;
}

- 11,492
- 14
- 59
- 94
-
4With gcc 4.8.4 and -O3, I get no difference. Without -O3 and 40000 iterations, I get *maybe* 50 ms less on a 1.5s total time, but I didn't run it enough times to know if that was even statistaclly significant. – zstewart Feb 22 '17 at 17:22
-
There's no difference with CLANG 5.0, platform is AMD64. (I've checked the ASM output.) – ern0 Oct 10 '17 at 10:10
You are messing with the compiler's sophisticated graph-coloring algorithm. This is used for register allocation. Well, mostly. It acts as a hint to the compiler -- that's true. But not ignored in its entirety since you are not allowed to take the address of a register variable (remember the compiler, now on your mercy, will try to act differently). Which in a way is telling you not to use it.
The keyword was used long, long back. When there were only so few registers that could count them all using your index finger.
But, as I said, deprecated doesn't mean you cannot use it.

- 108,024
- 16
- 131
- 187
-
13Some of the older hardware had more registers than the modern Intel machines. Register counts have nothing to do with age and everything to do with CPU architecture. – JUST MY correct OPINION Sep 30 '10 at 08:14
-
2@JUSTMYcorrectOPINION Indeed, X86 has basically six in all, leaving at most 1 or 2 for dedication to 'register'. In fact, since so much code has been written or ported to a register-poor machine, I suspect this contributed greatly to the 'register' keyword becoming a placebo - no point in hinting registers when there aren't any. Here we are 4+ years later and thankfully x86_64 has upped it to 14, and ARM is a big thing now too. – greggo Feb 21 '15 at 22:47
I have tested the register keyword under QNX 6.5.0 using the following code:
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <sys/neutrino.h>
#include <sys/syspage.h>
int main(int argc, char *argv[]) {
uint64_t cps, cycle1, cycle2, ncycles;
double sec;
register int a=0, b = 1, c = 3, i;
cycle1 = ClockCycles();
for(i = 0; i < 100000000; i++)
a = ((a + b + c) * c) / 2;
cycle2 = ClockCycles();
ncycles = cycle2 - cycle1;
printf("%lld cycles elapsed\n", ncycles);
cps = SYSPAGE_ENTRY(qtime) -> cycles_per_sec;
printf("This system has %lld cycles per second\n", cps);
sec = (double)ncycles/cps;
printf("The cycles in seconds is %f\n", sec);
return EXIT_SUCCESS;
}
I got the following results:
-> 807679611 cycles elapsed
-> This system has 3300830000 cycles per second
-> The cycles in seconds is ~0.244600
And now without register int:
int a=0, b = 1, c = 3, i;
I got:
-> 1421694077 cycles elapsed
-> This system has 3300830000 cycles per second
-> The cycles in seconds is ~0.430700

- 91
- 1
- 5
During the seventies, at the very beginning of the C language, the register keyword has been introduced in order to allow the programmer to give hints to the compiler, telling it that the variable would be used very often, and that it should be wise to keep it’s value in one of the processor’s internal register.
Nowadays, optimizers are much more efficient than programmers to determine variables that are more likely to be kept into registers, and the optimizer does not always take the programmer’s hint into account.
So many people wrongly recommend not to use the register keyword.
Let’s see why!
The register keyword has an associated side effect: you can not reference (get the address of) a register type variable.
People advising others not to use registers takes wrongly this as an additional argument.
However, the simple fact of knowing that you can not take the address of a register variable, allows the compiler (and its optimizer) to know that the value of this variable can not be modified indirectly through a pointer.
When at a certain point of the instruction stream, a register variable has its value assigned in a processor’s register, and the register has not been used since to get the value of another variable, the compiler knows that it does not need to re-load the value of the variable in that register. This allows to avoid expensive useless memory access.
Do your own tests and you will get significant performance improvements in your most inner loops.
Register would notify the compiler that the coder believed this variable would be written/read enough to justify its storage in one of the few registers available for variable use. Reading/writing from registers is usually faster and can require a smaller op-code set.
Nowadays, this isn't very useful, as most compilers' optimizers are better than you at determining whether a register should be used for that variable, and for how long.

- 14,554
- 6
- 53
- 76
gcc 9.3 asm output, without using optimisation flags (everything in this answer refers to standard compilation without optimisation flags):
#include <stdio.h>
int main(void) {
int i = 3;
i++;
printf("%d", i);
return 0;
}
.LC0:
.string "%d"
main:
push rbp
mov rbp, rsp
sub rsp, 16
mov DWORD PTR [rbp-4], 3
add DWORD PTR [rbp-4], 1
mov eax, DWORD PTR [rbp-4]
mov esi, eax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov eax, 0
leave
ret
#include <stdio.h>
int main(void) {
register int i = 3;
i++;
printf("%d", i);
return 0;
}
.LC0:
.string "%d"
main:
push rbp
mov rbp, rsp
push rbx
sub rsp, 8
mov ebx, 3
add ebx, 1
mov esi, ebx
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
add rsp, 8
pop rbx
pop rbp
ret
This forces ebx
to be used for the calculation, meaning it needs to be pushed to the stack and restored at the end of the function because it is callee saved. register
produces more lines of code and 1 memory write and 1 memory read (although realistically, this could have been optimised to 0 R/Ws if the calculation had been done in esi
, which is what happens using C++'s const register
). Not using register
causes 2 writes and 1 read (although store to load forwarding will occur on the read). This is because the value has to be present and updated directly on the stack so the correct value can be read by address (pointer). register
doesn't have this requirement and cannot be pointed to. const
and register
are basically the opposite of volatile
and using volatile
will override the const optimisations at file and block scope and the register
optimisations at block-scope. const register
and register
will produce identical outputs because const does nothing on C at block-scope, so only the register
optimisations apply.
On clang, register
is ignored but const
optimisations still occur.

- 4,129
- 1
- 32
- 42
-
In gcc, the `register` keyword can have a huge impact on the quality of code generated without optimization. In some cases, using the `register` keyword may result in a compiler generating more efficient code at `-O0` than it can generate at higher optimization settings [e.g. at `-O0`, if a register-qualified object is loaded outside a loop, gcc will leave the load outside the loop, but at higher optimization settings it may replace the object with a constant that it ends up reloading within the loop]. – supercat Feb 09 '21 at 18:11
Register keyword tells compiler to store the particular variable in CPU registers so that it could be accessible fast. From a programmer's point of view register keyword is used for the variables which are heavily used in a program, so that compiler can speedup the code. Although it depends on the compiler whether to keep the variable in CPU registers or main memory.

- 680
- 8
- 16
Microsoft's Visual C++ compiler ignores the register
keyword when global register-allocation optimization (the /Oe compiler flag) is enabled.
See register Keyword on MSDN.

- 29,356
- 35
- 146
- 243
On supported C compilers it tries to optimize the code so that variable's value is held in an actual processor register.

- 12,756
- 13
- 56
- 92
Register indicates to compiler to optimize this code by storing that particular variable in registers then in memory. it is a request to compiler, compiler may or may not consider this request. You can use this facility in case where some of your variable are being accessed very frequently. For ex: A looping.
One more thing is that if you declare a variable as register then you can't get its address as it is not stored in memory. it gets its allocation in CPU register.

- 219
- 2
- 7
The register keyword is a request to the compiler that the specified variable is to be stored in a register of the processor instead of memory as a way to gain speed, mostly because it will be heavily used. The compiler may ignore the request.

- 17
- 4