Python and C
Python and C
Digital Instrumentation
André Wemans
February 9, 2024
Contents
1 Introduction 1
2 Python and C 1
2.1 Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
2.2 Import . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.3 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.3.1 C types in Arduino one . . . . . . . . . . . . . . . . . . . . . . . . 5
2.3.2 Declaring and assigning values to variables . . . . . . . . . . . . . 8
2.3.3 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
5 functions 12
1 Introduction
The syntax of Python and C are very similar and what the students have learned
concerning the way to think in programming in Introdução à Programação using Python
is also valid in C. But some significant differences in how both languages work can lead
to some unexpected results if the students are not aware of them, so the objective of this
small document is to highlight them to make the start of programming in C for Arduino
the easiest possible.
On a side note, there are several differences between Python and C, starting with
the fact that Python is an interpreted language while C is a compiled language. The
compilation is a new step that can bring initial confusion to the students that never used
it before, but in this course, the programs are small, with a single or very few files, and
more important all compilation is automatically made by the Arduino IDE and in this
way it should not bring any problems.
2 Python and C
2.1 Comments
A comment in a single line or part of a single line is:
1
1 # This is a comment
2 var = 5 # This is also a comment but only after #
3
1 // This is a comment
2 var = 5 // This also a comment after //
3
2.2 Import
To import the code in another file, module or library is very common in programming
since for one side to divide larger code into more manageable shucks is a way to ensure
better code and more easily edited and updated. And in the other hand, it has no logic to
be reinventing the wheel again, and if already there is a good library with the functions
and features we need the more efficient way is to use it in our code.
In Python importing a library or file can be done in some different ways, but usually
the more common is:
1 import numpy as np # Imports the numpy library
2
3 output = np . cos (0.0)
4
2
1 # include < stdio .h > // Library for standard input / output
2 # include < math .h > // Library for usual math funcions
3
4 output = cos (0.0) ;
5 printf ( " % f \ n " , output ) ;
6
2.3 Variables
Variables are one of the differences between Python and C that can lead to unexpected
results or even broken programs when a programmer passes from Python to C. To try to
understand the differences let’s first see how Python works.
The information in Python (the information but not the variables) can be of some
specific types, namely:
Integer number - int
String - str
Boolean - bool
There are other more complex types, like lists, ranges, functions, and so on, but for
the sake of comparing with C some of the ones above are the most important.
What happens when you run the following code in Python?
1 var_01 = 300
2 var_02 = var_01
3
4 var_01 = 15.5
5 var_02 = " String "
6
3
Figure 1: Memory after assigning value 300 to var 01
After running line two Python assigns the same memory address to var 02, and both
variables are now pointing to the same memory address, Figure 2
Python on line 4 will reserve a new memory space and stores the float 15.5 and assigns
that address to var 01, the final memory state can be seen in Figure 3
Finally, after line 5 Python reserves memory to store the string ”String” and assigns
that address to variable var 02, resulting in a memory state seen in Figure 4. Since no
more variables are pointing to the memory address that contains the integer 300 Python
behind scenes will free that memory to be available for other eventual uses, Figure 5
In resume, Python manages the reserve and release of memory, variables store memory
addresses but can be redirected to other memory address where completely different types
of information can be stored.
On a side note, Python does not always reserve new memory space every time the
information is changed, for example it is possible to alter elements in a list without
changing the memory where the initial list information is stored.
C works very differently, starting that a variable is declared with a type, the compiler
reserves an adequate amount of memory, and the variable in all program points to that
memory position. The value in the memory address can be altered for another value of
the same type but the variable always points to that memory address.
4
Figure 3: Memory after assigning 15.5 to var 01
5
Figure 5: Final memory state
Boolean - bool
Generally in C, the bool type is not completely native but in Arduino there is no need
to import the stdbool.h library and can be used as a native type. The bool type uses
exactly one Byte (8 bits) of memory space and can have the true or false values.
Please notice that in C if a value is evaluated in a conditional function it will be
considered true if not 0 and false if 0.
Character - char
Char is the type of variable that stores single characters. A single character is repre-
sented using single quotes, like ’A’. The char information uses 1 Byte of memory and it is
stored as an integer number, corresponding to the character’s ASCII code, for example,
’A’ is 65. This makes it possible to write something like ’A’+1, which will give ’B’ since
the ASCII code for ’B’ is 66.
Float-point number - float or double
The floating-point number in C has two sub-types that are different in the precision
and in the memory they use. float uses 4 Bytes and double has higher precision and uses
8 Bytes of memory.
Any value with a decimal point will be considered as double unless it ends in L for
each it will be considered float, like 3.1415L.
6
Integer - int, long, short, unsigned
The Integer values in C can vary in how much memory they use, the higher the
memory used the higher the range of values possible to use, if they are only positive, or
if they can also have negative values.
The int type in the Arduino Uno uses 2 Bytes of memory (in most compilers for
programs to be used in computers and some other Arduino boards usually use 4 Bytes).
The int type can have negative and positive values and uses the most significant bit
to codify if the number is negative, 1, or positive, 0. Since in the Arduino Uno the int
type uses 2 Bytes (16 bits) and the most significant bit is used to indicate if the number
is positive or negative, it leaves 15 bits to store the value information and can have values
from -32 768 to 32 767.
The short has the same proprieties as the int in the case of Arduino Uno.
The long instead of using 2 Bytes uses 4 Bytes which gives a range of values from -2
147 483 648 to 2 147 483 647.
Each of these types can be preceded by the modifier unsigned making the values
stored only zero or positive and increasing the higher value possible. For int, it will allow
a range from 0 to 65 536 and for long from 0 to 4 294 967 296.
If only integer type values are involved in a mathematical operation the final result
will be also an integer, even if that operation is the division, it will be an integer division
dropping any eventual information decimal information. The operation 3/2 will give 1
as result.
If more than one of the integer types is involved in a mathematical operation the
compiler will make an automatic cast of the type with lesser memory and from signed to
unsigned. This automatic cast can sometimes lead to unexpected results if the program-
mer is not aware of its consequences.
Finally, if it is used a mathematical operation using both floating-point and integer
numbers the cast is always the integer passing to float or double.
As an example 3/2 gives 1, but 3./2 gives 1.5 since 3. is a double value, leading to 2
being cast to double and it will be equivalent to having 3./2.
The cast is the operation in which a value of a given type is transformed to another
type, and it can be made explicitly by the programmer or automatically by the compiler.
Both ways work exactly the same way, the difference is only that in the latter the pro-
grammer can be not aware of the cast and eventually unaware of some problem that can
arise from it.
The automatic cast can arise from two distinct situations, first if a mathematical
operation is made on two different types of values. In that case, there is a type chain of
precedence where the one with a lesser high range is converted into the type of the one
with a higher high range, as can be seen in Figure 6.
Usually, the result of the operation will give the mathematical expected output and
all will work fine. But there is also potential for different results, for example comparing
7
int → unsigned int → long → unsigned long → ... → f loat → double
−1 < 10 with 10 being an unsigned value will give false since -1 converted to unsigned
will be the highest value possible for that unsigned type.
The second possible way of having an automatic cast is when assigning a value of a
type to a variable of another type. In that case, the type of the variable is dominant and
the value being assigned to it will always be cast to the same type as the variable, even
if this means losing information.
A floating or double value being assigned to any kind of integer variable will always
lose the decimal information and an integer value higher than what the integer variable
can store will lose the higher Bytes.
8
A variable is valid in the scope it is declared, if declared inside a function it is only
valid inside that function.
And contrary to Python, when a variable is assigned to another one it is not the case
that they are both pointing to the same memory address, but instead the value in the
variable on the right is copied to the variable on the left.
2.3.3 Arrays
In C there are no Lists, Dictionaries, and other data structures presented in Python.
C has Arrays, Unions, and Structures but we will only look at Arrays here. An array
is a continuous memory space reserved to store some value type information, and it is
declared as it can be seen in Listing 11.
1
9
and since that code is incorrect the compiler will give an error and not compile the
program.
Also in C to write a block of code inside an if or other control functions the indentation
is ignored and the code block must be inside {}. The fact the compiler works without
problem if the code is not correctly indentation does not excuse writing without proper
indentation. Contrary to Python, it is not necessary for the program to run but it is
necessary for the code to be easily read by humans.
10
10 case 100:
11 printf ( " Higher than 50 " ) ;
12 break ;
13 default :
14 printf ( " Unknown " ) ;
15 }
16
4.2 While
The while function works as in Python, see Listing 16.
1 int value = 100;
2 int count = 0;
3
4 while ( value > 10) {
5 value -= 10;
6 count ++;
7 }
8
9 printf ( value ) ;
10
4.3 For
The for function works very differently in C than in Python, see Listing 17.
1
2 int count = 0;
3
4 for ( int i = 0; i < 100; i += 5) {
5 printf ( i ) ;
6 count ++;
7 }
8
9 printf ( count ) ;
10
11
Inside the for, the first expression initializes the control variable i (it can be any name
inside variable names rules), the second expression is checked every turn of the for and
if it is false stops the for, and finally the last expression defines the change in the for
control variable.
5 functions
Like in Python, it is possible to define user-made functions, the difference is the
arguments have types and the function has also a type defined for the output of the
function, see Listing 18, where is defined a function to compute the power between two
integer numbers.
1
2 unsigned long power ( unsigned base , unsigned expoent ) {
3 unsigned long result = 1;
4
5 for ( unsigned i = 0; i < expoent ; i ++) {
6 result *= base ;
7 }
8
9 return result ;
10 }
11
12