Академический Документы
Профессиональный Документы
Культура Документы
Dark corner of C
Here it is!
Shadowy escape
int x = 42;
int func() {
int x = 3840;
{
return x;
}
}
Returns 3840
int x = 42;
int func() {
int x = 3840;
{
extern int x;
return x;
}
}
Returns 42
[ ] is just + in disguise
assert(spong[x] == x[spong]);
assert(spong[2] == 2[spong]);
d = "0123456789abcdef"[n];
d = n["0123456789abcdef"];
Pointer aliasing
void foo1(int *x, int *y, int *z) {
*x += *z;
Compiler
*y += *z;
doesn't
}
know that *z
movl (%rdx), %eax
won't also be
addl %eax, (%rdi)
*x, so loads
movl (%rdx), %eax
it twice :(
addl %eax, (%rsi)
ret
Counting up ...
int fact1(int n) {
int i, fact = 1;
for (i = 1; i <= n;
i++)
fact *= i;
return fact;
}
fact1:
movl
testl
jle
xorl
.loop:
incl
imull
cmpl
jne
.exit
ret
$1, %eax
%edi, %edi
.exit
%ecx, %ecx
%ecx
%ecx, %eax
%ecx, %edi
.loop
fact2:
testl
movl
je
.loop:
imull
subl
jne
.exit:
ret
%edi, %edi
$1, %eax
.exit
%edi, %eax
$1, %edi
.loop
const confusion
const int foo = 10;
const int *foop = &foo;
"Constant" integer foo with value 10.
And a "constant" pointer to it?
int i = 20;
foop = &i;
Oops. const binds left. But if there's
nothing to its left, it binds to the right.
Munchy munchy.
z = y+++x;
The C specification says that when there is such
an ambiguity, munch as much as possible. (The
"greedy lexer rule".)
z = y++ + x;
C keywords
auto break case char const continue default do
double else enum extern float for goto if int
long register restrict return short signed sizeof
static struct switch typedef union unsigned void
volatile while
Wait, what? auto is a bizarreness left over from B. The only
place it's valid, it's also the default. And that's to say a
variable should be automatically managed, ie, placed on the
stack. static is its antonym. Ish.
Smallest C program
What's the smallest C program that will
compile and link?
main;
Alas it produces a warning. So we can do this:
int main;
(Don't run this.)
C++: 10
C99: 10
Recommended reads