Instructor: Stefan Mitsch
if
void f (int x) {
int y = x + 1;
if (x > y) {
int z = y + 1;
printf ("z = %d\n", z);
}
}
y = 5*x; // Free occurrences of x and y
int y; // binding occurrence of y
int y; // Binding occurrence of y
int x; // Binding occurrence of x
x=6; // Bound occurrence of x
y = 5*x; // Bound occurrences of x and y
char f (int x);
char g (int x) {
return f (x) + f (x);
}
char f (int x) {
if (x > 0) {
return g (x >> 8);
} else {
return 1;
}
}
public class C {
static void f () {
int x = 1;
{
int y = x + 1;
{
int x = y + 1;
System.out.println ("x = " + x);
}
}
}
}
$ javac C.java
C.java:7: error: variable x is already defined in method f()
int x = y + 1;
^
1 error
public class C {
static int x = 1;
static void f () {
int y = x + 1;
{
int x = y + 1;
System.out.println ("x = " + x);
}
}
public static void main (String[] args) {
f ();
}
}
$ javac C.java
$ java C
x = 3
int main () {
int x = 1;
{
int y = x + 1;
{
int x = y + 1;
printf ("x = %d\n", x);
}
}
}
$ gcc -o scope scope.c
$ ./scope
x = 3
object C:
def f () =
var x = 1;
var y = x + 1;
var x = y + 1;
println ("x = " + x)
def main (args:Array[String]) =
f ()
$ scalac C.scala
$ scala C
x = 3
scala> val x = 1
x: Int = 1
scala> def f (a:Int) = x + a
f: (a: Int)Int
scala> f (10)
res0: Int = 11
scala> val x = 2
x: Int = 2
scala> x
res1: Int = 2
scala> f (10)
res2: Int = 11
{
val x = 1;
def f (a:Int) = x + a
f (10)
{
val x = 2;
x
f (10)
...
}
}
x in scope?
int main (void) {
int x = 10;
{
int x = x + 1;
printf ("x = %08x\n", x);
}
return 0;
}
$ gcc -o scope scope.c
$ gcc -Wall -o scope scope.c
scope.c: In function ‘main’:
scope.c:5:7: warning: unused variable ‘x’ [-Wunused-variable]
scope.c:7:9: warning: ‘x’ is used uninitialized in this function [-Wuninitialized]
$ ./scope
x = 00000001
ebp register points to AR for most recently called function
freed heap memory
freeing of heap memory
#include <stdio.h>
#include <stdlib.h>
int *f (int x) {
int y = x;
return &y;
}
int main (void) {
int *p = f (1);
printf ("*p = %d\n", *p);
return 0;
}
$ gcc -o ar ar.c
ar.c: In function ‘f’:
ar.c:6:3: warning: function returns address of local variable
[enabled by default]
$ ./ar
*p = 1
$ valgrind ./ar
==5505== Memcheck, a memory error detector
==5505== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==5505== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==5505== Command: ./ar
==5505==
==5505== Conditional jump or move depends on uninitialised value(s)
==5505== at 0x4E7C1A1: vfprintf (vfprintf.c:1596)
==5505== by 0x4E85298: printf (printf.c:35)
==5505== by 0x400536: main (in /tmp/ar)
==5505==
==5505== Use of uninitialised value of size 8
==5505== at 0x4E7A49B: _itoa_word (_itoa.c:195)
==5505== by 0x4E7C4E7: vfprintf (vfprintf.c:1596)
==5505== by 0x4E85298: printf (printf.c:35)
==5505== by 0x400536: main (in /tmp/ar)
==5505==
==5505== Conditional jump or move depends on uninitialised value(s)
==5505== at 0x4E7A4A5: _itoa_word (_itoa.c:195)
==5505== by 0x4E7C4E7: vfprintf (vfprintf.c:1596)
==5505== by 0x4E85298: printf (printf.c:35)
==5505== by 0x400536: main (in /tmp/ar)
==5505==
*p = 1
==5505==
==5505== HEAP SUMMARY:
==5505== in use at exit: 0 bytes in 0 blocks
==5505== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==5505==
==5505== All heap blocks were freed -- no leaks are possible
==5505==
==5505== For counts of detected and suppressed errors, rerun with: -v
==5505== Use --track-origins=yes to see where uninitialised values come from
==5505== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 2 from 2)
#include <stdio.h>
#include <stdlib.h>
int *f (int x) {
int *result = (int *) malloc (sizeof (int));
*result = x;
return result;
}
int main (void) {
int *p = f (1);
printf ("*p = %d\n", *p);
return 0;
}
$ gcc -Wall -o ar ar.c
$ ./ar
*p = 1
$ valgrind ./ar
==10962== Memcheck, a memory error detector
==10962== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==10962== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==10962== Command: ./ar
==10962==
*p = 1
==10962==
==10962== HEAP SUMMARY:
==10962== in use at exit: 4 bytes in 1 blocks
==10962== total heap usage: 1 allocs, 0 frees, 4 bytes allocated
==10962==
==10962== LEAK SUMMARY:
==10962== definitely lost: 4 bytes in 1 blocks
==10962== indirectly lost: 0 bytes in 0 blocks
==10962== possibly lost: 0 bytes in 0 blocks
==10962== still reachable: 0 bytes in 0 blocks
==10962== suppressed: 0 bytes in 0 blocks
==10962== Rerun with --leak-check=full to see details of leaked memory
==10962==
==10962== For counts of detected and suppressed errors, rerun with: -v
==10962== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
#include <stdio.h>
#include <stdlib.h>
int *f (int x) {
int *result = (int *) malloc (sizeof (int));
*result = x;
return result;
}
int main (void) {
int *p = f (1);
free (p);
printf ("*p = %d\n", *p);
return 0;
}
$ gcc -Wall -o ar ar.c
$ ./ar
*p = 0
$ valgrind ./ar
==13594== Memcheck, a memory error detector
==13594== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==13594== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==13594== Command: ./ar
==13594==
==13594== Invalid read of size 4
==13594== at 0x4005D2: main (in /tmp/ar)
==13594== Address 0x51f0040 is 0 bytes inside a block of size 4 free'd
==13594== at 0x4C2A82E: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13594== by 0x4005CD: main (in /tmp/ar)
==13594==
*p = 1
==13594==
==13594== HEAP SUMMARY:
==13594== in use at exit: 0 bytes in 0 blocks
==13594== total heap usage: 1 allocs, 1 frees, 4 bytes allocated
==13594==
==13594== All heap blocks were freed -- no leaks are possible
==13594==
==13594== For counts of detected and suppressed errors, rerun with: -v
==13594== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)
x in the initializer, x + 1
int main (void) {
int x = 10;
{
int x = x + 1;
printf ("x = %08x\n", x);
}
return 0;
}
$ gcc -o scope scope.c
$ gcc -Wall -o scope scope.c
scope.c: In function ‘main’:
scope.c:5:7: warning: unused variable ‘x’ [-Wunused-variable]
scope.c:7:9: warning: ‘x’ is used uninitialized in this function [-Wuninitialized]
$ ./scope
x = 00000001
class C {
public static void main (String[] args) {
int x = 1 + x;
System.out.printf ("x = %08x\n", x);
}
}
x.java:3: error: variable x might not have been initialized
int x = 1 + x;
^
1 error
scala> val x:Int = 1 + x
x: Int = 1
scala> :javap -p -c -filter -
Compiled from "<console>"
public class {
private final int x;
public int x();
0: aload_0
1: getfield #22 // Field x:I
4: ireturn
public ();
...
10: invokevirtual #28 // Method x:()I
13: iconst_1
14: iadd
15: putfield #22 // Field x:I
...
}
null != Nil
scala> val xs:List[Int] = 1 :: xs
java.lang.NullPointerException
... 28 elided
scala> case class S(head:Int, tail:S)
defined class S
scala> val ss:S = S(1, ss)
ss: S = S(1,null)
scala> case class T(head:Int, tail:()=>T)
defined class T
scala> val ts:T = T(1, ()=>ts)
ts: T = T(1,$$Lambda$1324/2038353966@4d500865)
scala> ts.tail().tail().head
res14: Int = 1
#:: is non-strict in right-hand argument
scala> val ones:Stream[Int] = 1 #:: ones
ones: Stream[Int] = Stream(1, ?)
scala> ones.take (5)
res0: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> ones.take (5).toList
res1: List[Int] = List(1, 1, 1, 1, 1)
scala> def f (x:Int) : Stream[Int] = { { println (s"f(${x})"); x } #:: f(x+1) }
f: (x: Int)Stream[Int]
scala> val xs:Stream[Int] = f(10)
f(10)
xs: Stream[Int] = Stream(10, <not computed>)
scala> xs.take(4).toList
f(11)
f(12)
f(13)
res12: List[Int] = List(10, 11, 12, 13)
scala> xs.take(4).toList
res13: List[Int] = List(10, 11, 12, 13)
scala> xs.take(6).toList
f(14)
f(15)
res14: List[Int] = List(10, 11, 12, 13, 14, 15)
scala> def f (x:Int) : LazyList[Int] = { { println (s"f(${x})"); x } #:: f(x+1) }
f: (x: Int)LazyList[Int]
scala> val xs:LazyList[Int] = f(10)
xs: LazyList[Int] = <not computed>
scala> xs.take(4).toList
f(10)
f(11)
f(12)
f(13)
res12: List[Int] = List(10, 11, 12, 13)
scala> xs.take(4).toList
res13: List[Int] = List(10, 11, 12, 13)
scala> xs.take(6).toList
f(14)
f(15)
res14: List[Int] = List(10, 11, 12, 13, 14, 15)
var x:Int = 10
def foo () =
x = 20
def bar () =
var x:Int = 30
foo ()
bar ()
println (x)
z come from?
...
def g (x:Int) : Int =
var y:Int = x * 2
z * x * y // x and y are local; z is non-local
var x:Int = 10
def foo () : Unit =
x = 20
def bar () : Unit =
var x:Int = 30
foo ()
bar ()
println (x)
Bash (prints 10):
x=10
function foo() {
x=20
}
function bar() {
local x=30
foo
}
bar
echo $x
C functions (prints 20):
int x = 10;
void foo () {
x = 20;
}
void bar () {
int x = 30;
foo ();
}
int main () {
bar ();
printf ("x=%d\n", x);
}
C macros (prints 10):
int x = 10;
#define foo() { \
x = 20; \
}
#define bar() { \
int x = 30; \
foo (); \
}
int main () {
bar ();
printf ("x=%d\n", x);
}
Python (prints 20):
def main():
def foo ():
nonlocal x
x = 20
def bar ():
x = 30
foo ()
x = 10
bar ()
print (x)
main()
Python (prints 20):
def foo ():
global x
x = 20
def bar ():
x = 30
foo ()
x = 10
def main():
bar ()
print (x)
main()
Python global scope is not static
def useX():
print (x)
def defX():
global x
x = 1
>>> useX()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in useX
NameError: name 'x' is not defined
>>> defX()
>>> useX()
1
Emacs Lisp (prints "10"):
(let ((x 10))
(defun foo ()
(setq x 20))
(defun bar ()
(let ((x 30))
(foo)))
(bar)
(message (int-to-string x)))
Common Lisp (prints 20):
(let ((x 10))
(defun foo ()
(setq x 20))
(defun bar ()
(let ((x 30))
(foo)))
(bar)
(print x))
Scheme (prints 20):
(let ((x 10))
(define (foo)
(set! x 20))
(define (bar)
(let ((x 30))
(foo)))
(bar)
(display x)
(newline))
Perl (prints 10):
local $x = 10;
sub foo {
$x = 20;
}
sub bar {
local $x = 30;
foo ();
}
bar ();
print ($x);
Perl (prints 20):
my $x = 10;
sub foo {
$x = 20;
}
sub bar {
my $x = 30;
foo ();
}
bar ();
print ($x);