C變量和類型

關於使用C語言處理變量以及基本類型的介紹

C是一種靜態類型的語言。

這意味著任何變量都具有關聯的類型,並且該類型在編譯時是已知的。

這與處理Python,JavaScript,PHP和其他解釋語言中的變量的方式非常不同。

在C語言中創建變量時,必須在聲明中指定變量的類型。

在這個例子中,我們初始化一個變量age與類型int

int age;

變量名可以包含任何大寫或小寫字母,可以包含數字和下劃線字符,但不能以數字開頭。AGEAge10是有效的變量名,1age不是。

您還可以在聲明時初始化變量,並指定初始值:

int age = 37;

聲明變量後,便可以在程序代碼中使用它,並且可以隨時使用=運算符,例如inage = 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: