C变量和类型

C语言中变量的介绍以及基本类型

C是一种静态类型的语言。

这意味着任何变量都具有关联的类型,并且该类型在编译时是已知的。

这与处理Python,JavaScript,PHP和其他解释语言中的变量的方式非常不同。

在C语言中创建变量时,必须在声明中指定变量的类型。

在这个例子中,我们初始化一个变量age与类型int

int age;

变量名可以包含任何大写或小写字母,可以包含数字和下划线字符,但不能以数字开头。AGEAge10是有效的变量名,1age不是。

您还可以在声明时初始化变量,并指定初始值:

int age = 37;

声明变量后,便可以在程序代码中使用它,并且可以随时使用=例如运算符,例如age = 100;,前提是新值的类型相同。

在这种情况下:

#include <stdio.h>

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

编译器将在编译时发出警告,并将十进制数转换为整数值。

C内置数据类型是intcharshortlongfloatdoublelong double。让我们更多地了解这些。

整数

C为我们提供了以下类型来定义整数值:

  • char
  • int
  • short
  • long

在大多数情况下,您可能会使用int存储一个整数。但是在某些情况下,您可能要选择其他三个选项之一。

chartype通常用于存储ASCII图表的字母,但可以用于保存ASCII图表中的小整数-128127。至少需要1个字节。

int至少占用2个字节。short至少占用2个字节。long至少占用4个字节。

如您所见,我们不能保证在不同环境下使用相同的值。我们只有一个指示。问题在于每种数据类型中可以存储的确切数字取决于实现和体系结构。

我们保证short不超过int。而且我们保证long不小于int

ANSI C规范标准确定每种类型的最小值,并且由于它,我们至少可以知道我们可以期望的最小值是多少。

如果您在Arduino上进行C语言编程,则不同的开发板将具有不同的限制。

在Arduino Uno板上,int存储一个2字节的值,范围从-32,76832,767. On a Arduino MKR 1010, int存储一个4字节的值,范围从-2,147,483,6482,147,483,647。差异很大。

在所有Arduino板上,short存储2个字节的值,范围从-32,76832,767long存储4个字节,范围从-2,147,483,6482,147,483,647

无符号整数

对于上述所有数据类型,我们可以在前面添加unsigned将范围从0开始,而不是负数。在许多情况下,这可能是有道理的。

  • unsigned char范围从0至少255
  • unsigned int范围从0至少65,535
  • unsigned short范围从0至少65,535
  • unsigned long范围从0至少4,294,967,295

溢出问题

考虑到所有这些限制,可能会出现一个问题:我们如何确保我们的人数不超过该限制?而我们超出限制会发生什么呢?

如果您有unsigned int数字为255,然后增加它,您将获得256的回报。如预期的那样。如果你有一个unsigned char数字为255,然后增加它,您将得到0。从可能的初始值开始复位。

如果你有一个unsigned char在255处加上10,就可以得到9

#include <stdio.h>

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

如果您有一个带符号的值,则行为是不确定的。基本上,它将为您提供数量庞大的数字,可能会有所不同,例如在这种情况下:

#include <stdio.h>

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

换句话说,C不能保护您避免超出类型的限制。您需要自己照顾这一点。

声明错误类型时的警告

当您声明变量并使用错误的值对其进行初始化时,gcc编译器(您可能正在使用的编译器)应警告您:

#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: