## 2.3 Variables and Arithmetic Expressions

Our next example program makes use of the DTrace `profile` provider to implement a simple time-based counter. The profile provider is able to create new probes based on the descriptions found in your D program. If you create a probe named `profile:::tick-``n``sec` for some integer `n`, the profile provider creates a probe that fires every `n` seconds. Type the following source code and save it in a file named `counter.d`:

```/*
* Count off and report the number of seconds elapsed
*/

dtrace:::BEGIN
{
i = 0;
}

profile:::tick-1sec
{
i = i + 1;
trace(i);
}

dtrace:::END
{
trace(i);
}```

When executed, the program counts off the number of elapsed seconds until you press `Ctrl-C`, and then prints the total at the end:

```# `dtrace -s counter.d`
dtrace: script 'counter.d' matched 3 probes
CPU     ID                    FUNCTION:NAME
1    638                       :tick-1sec         1
1    638                       :tick-1sec         2
1    638                       :tick-1sec         3
1    638                       :tick-1sec         4
1    638                       :tick-1sec         5
1    638                       :tick-1sec         6
1    638                       :tick-1sec         7
`^C`
1    638                       :tick-1sec         8
0      2                             :END         8```

The first three lines of the program are a comment to explain what the program does. Similar to C, C++, and the Java programming language, the D compiler ignores any characters between the `/*` and `*/` symbols. Comments can be used anywhere in a D program, including both inside and outside your probe clauses.

The `BEGIN` probe clause defines a new variable named `i` and assigns it the integer value zero using the statement:

`i = 0;`

Unlike C, C++, and the Java programming language, D variables can be created by simply using them in a program statement; explicit variable declarations are not required. When a variable is used for the first time in a program, the type of the variable is set based on the type of its first assignment. Each variable has only one type over the lifetime of the program, so subsequent references must conform to the same type as the initial assignment. In `counter.d`, the variable `i` is first assigned the integer constant zero, so its type is set to `int`. D provides the same basic integer data types as C, including those in the following table.

Data Type

Description

`char`

Character or single byte integer

`int`

Default integer

`short`

Short integer

`long`

Long integer

`long long`

Extended long integer

The sizes of these types are dependent on the operating system kernel's data model, described in Section 2.8, “Types, Operators, and Expressions”. D also provides built-in friendly names for signed and unsigned integer types of various fixed sizes, as well as thousands of other types that are defined by the operating system.

The central part of `counter.d` is the probe clause that increments the counter `i`:

```profile:::tick-1sec
{
i = i + 1;
trace(i);
}```

This clause names the probe `profile:::tick-1sec`, which tells the `profile` provider to create a new probe that fires once per second on an available processor. The clause contains two statements, the first incrementing `i`, and the second tracing (printing) the new value of `i`. All the usual C arithmetic operators are available in D. For the complete list, see Section 2.8, “Types, Operators, and Expressions”. The ` trace` function takes any D expression as its argument, so you could write `counter.d` more concisely as follows:

```profile:::tick-1sec
{
trace(++i);
}```

If you want to explicitly control the type of the variable `i`, you can surround the desired type in parentheses when you assign it in order to cast the integer zero to a specific type. For example, if you wanted to determine the maximum size of a `char` in D, you could change the `BEGIN` clause as follows:

```dtrace:::BEGIN
{
i = (char)0;
}```

After running counter.d for a while, you should see the traced value grow and then wrap around back to zero. If you grow impatient waiting for the value to wrap, try changing the `profile` probe name to `profile:::tick-100msec` to make a counter that increments once every 100 milliseconds, or 10 times per second.