C variables and types

Introduction and basic types of variables in C language

C is a statically typed language.

This means that any variable has an associated type, and the type is known at compile time.

This is very different from the way variables in Python, JavaScript, PHP and other interpreted languages are handled.

When creating a variable in C language, the type of the variable must be specified in the declaration.

In this example, we initialize a variableageAnd typeint:

int age;

Variable names can contain any uppercase or lowercase letters, can contain numbers and underscore characters, but cannot start with a number.AGEwithAge10Is a valid variable name,1ageIt's not.

You can also initialize variables at the time of declaration and specify initial values:

int age = 37;

After the variable is declared, it can be used in the program code and can be used at any time=For example, operators, such asage = 100;, Provided that the new value is of the same type.

under these circumstances:

#include <stdio.h>

int main(void) {
	int age = 0;
	age = 37.2;
	printf("%u", age);
}

The compiler will issue a warning at compile time and convert the decimal number to an integer value.

ThisCThe built-in data types areint,char,short,long,float,double,long double. Let us know more about these.

Integer

C provides us with the following types to define integer values:

  • char
  • int
  • short
  • long

In most cases, you might useintStore an integer. But in some cases, you may want to choose one of the other three options.

Thischartype is usually used to store the letters of the ASCII chart, but can be used to store small integers in the ASCII chart-128To127. At least 1 byte is required.

intIt occupies at least 2 bytes.shortIt occupies at least 2 bytes.longIt occupies at least 4 bytes.

As you can see, we cannot guarantee that the same value will be used in different environments. We have only one instruction. The problem is that the exact number that can be stored in each data type depends on the implementation and architecture.

We promiseshortDoes not exceedint. And we guaranteelongnot less thanint.

The ANSI C specification standard determines the minimum value of each type, and because of it, we can at least know what the minimum value we can expect.

If you program in C language on Arduino, different development boards will have different restrictions.

On the Arduino Uno board,intStore a 2-byte value, ranging from-32,768To32,767. On a Arduino MKR 1010, intStore a 4-byte value, ranging from-2,147,483,648To2,147,483,647. big difference.

On all Arduino boards,shortStore the value of 2 bytes, ranging from-32,768To32,767.longStore 4 bytes, ranging from-2,147,483,648To2,147,483,647.

Unsigned integer

For all the above data types, we can add in frontunsignedStart the range from 0 instead of negative numbers. In many cases, this may make sense.

  • unsigned charRange from0at least255
  • unsigned intRange from0at least65,535
  • unsigned shortRange from0at least65,535
  • unsigned longRange from0at least4,294,967,295

Overflow problem

Considering all these restrictions, a question may arise: how do we ensure that our number does not exceed that limit? And what happens if we exceed the limit?

If you haveunsigned intThe number is 255, and then increase it, and you will get 256 in return. As expected. If you have oneunsigned charThe number is 255, then increase it and you will get 0. Start resetting from possible initial values.

If you have oneunsigned charAdd 10 to 255 to get9:

#include <stdio.h>

int main(void) {
  unsigned char j = 255;
  j = j + 10;
  printf("%u", j); /* 9 */
}

If you have a signed value, the behavior is undefined. Basically, it will provide you with a huge number of numbers, which may be different, for example in this case:

#include <stdio.h>

int main(void) {
  char j = 127;
  j = j + 10;
  printf("%u", j); /* 4294967177 */
}

In other words, C cannot protect you from exceeding the type limit. You need to take care of this yourself.

Warning when declaring wrong type

When you declare a variable and initialize it with the wrong value,gccThe compiler (the one you may be using) should warn you:

#include <stdio.h>

int main(void) {
  char j = 1000;
}
hello.c:4:11: warning: implicit conversion from 'int' to
      'char' changes value from 1000 to -24
      [-Wconstant-conversion]
        char j = 1000;
             ~   ^~~~
1 warning generated.

And it also warns you in direct assignments:

#include <stdio.h>

int main(void) {
  char j;
  j = 1000;
}

But not if you increase the number using for example +=:

#include <stdio.h>

int main(void) {
  char j = 0;
  j += 1000;
}

Floating point numbers

Floating point types can represent a much larger set of values than integers can, and can also represent fractions, something that integers can’t do.

Using floating point numbers, we represent numbers as decimal numbers times powers of 10.

You might see floating point numbers written as

  • 1.29e-3
  • -2.3e+5

and in other seemingly weird ways.

The following types:

  • float
  • double
  • long double

are used to represent numbers with decimal points (floating point types). All can represent both positive and negative numbers.

The minimum requirements for any C implementation is that float can represent a range between 10^-37 and 10^+37, and is typically implemented using 32 bits. double can represent a bigger set of numbers. long double can hold even more numbers.

The exact figures, as with integer values, depend on the implementation.

On a modern Mac, a float is represented in 32 bits, and has a precision of 24 significant bits, 8 bits are used to encode the exponent. A double number is represented in 64 bits, with a precision of 53 significant bits, 11 bits are used to encode the exponent. The type long double is represented in 80 bits, has a precision of 64 significant bits, 15 bits are used to encode the exponent.

On your specific computer, how can you determine the specific size of the types? You can write a program to do that:

#include <stdio.h>

int main(void) {
  printf("char size: %lu bytes\n", sizeof(char));
  printf("int size: %lu bytes\n", sizeof(int));
  printf("short size: %lu bytes\n", sizeof(short));
  printf("long size: %lu bytes\n", sizeof(long));
  printf("float size: %lu bytes\n", sizeof(float));
  printf("double size: %lu bytes\n", sizeof(double));
  printf("long double size: %lu bytes\n", sizeof(long double));
}

In my system, a modern Mac, it prints:

char size: 1 bytes
int size: 4 bytes
short size: 2 bytes
long size: 8 bytes
float size: 4 bytes
double size: 8 bytes
long double size: 16 bytes  

Download my free C Handbook


More clang tutorials: