C/C++(2)基本语法和数据类型

简介: C/C++(2)基本语法和数据类型

C和C是两种非常流行和强大的编程语言,它们都是由贝尔实验室的丹尼斯·里奇(Dennis Ritchie)和比雅尼·斯特劳斯特鲁普(Bjarne Stroustrup)分别在1972年和1985年开发的。C语言是一种结构化的、过程式的、通用的编程语言,它可以用来编写各种类型的程序,如操作系统、数据库、编译器等。C语言是一种在C语言基础上发展而来的、支持面向对象编程和泛型编程的编程语言,它可以用来编写更复杂和高效的程序,如图形界面、游戏、网络应用等。

C和C++有很多相同的语法和数据类型,但也有一些不同和扩展。我们来看一些基本的语法和数据类型。

注释、变量、常量、运算符、表达式等

注释是程序中用来说明代码功能或逻辑的文字,它不会被编译器执行,只是给人阅读的。C和C++都支持两种注释方式:单行注释和多行注释。单行注释以//开头,多行注释以/*开头,以*/结尾。例如:

// 这是一个单行注释
/* 这是一个
多行注释 */

变量是程序中用来存储数据的标识符,它有一个名字和一个类型。变量必须先声明后使用,声明时要指定变量的类型和名字,可以同时赋初值。例如:

int a; // 声明一个整型变量a
a = 10; // 给a赋值为10
double b = 3.14; // 声明一个双精度浮点型变量b,并赋值为3.14
char c = 'A'; // 声明一个字符型变量c,并赋值为'A'

常量是程序中不会改变的数据,它有一个值和一个类型。常量可以用字面量表示,如103.14'A'等,也可以用const关键字定义一个常量变量,如const int MAX = 100;。常量变量一旦定义就不能再修改。

运算符是程序中用来对数据进行操作的符号,如加减乘除等。表达式是由运算符和操作数(变量或常量)组成的式子,如a + b * c等。运算符有不同的优先级和结合性,可以用括号改变计算顺序。例如:

int a = 10, b = 20, c = 30;
int d = a + b * c; // d = 610, 因为乘法优先于加法
int e = (a + b) * c; // e = 900, 因为括号优先于乘法
基本数据类型(整型、浮点型、字符型等)和复合数据类型(数组、结构体等)

下面是C和C++语言中的所有基本数据类型的详细表格,包括它们之间的差异:

类型 描述 存储大小 值范围 C支持 C++支持
bool 布尔类型,表示真或假 1字节 true 或 false
char 通常用于存储字符型数据 1字节 -128 到 127 或 0 到 255
unsigned char 无符号字符型 1字节 0 到 255
signed char 有符号字符型 1字节 -128 到 127
int 用于存储整数 2 或 4字节 -32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647
unsigned int 无符号整型 2 或 4字节 0 到 65,535 或 0 到 4,294,967,295
short 用于存储短整数 2字节 -32,768 到 32,767
unsigned short 无符号短整型 2字节 0 到 65,535
long 用于存储长整数 4字节 -2,147,483,648 到 2,147,483,647
unsigned long 无符号长整型 4字节 0 到 4,294,967,295
long long 用于存储更大的整数 8字节 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 是(C99起)
unsigned long long 无符号更大的整型 8字节 0 到 18,446,744,073,709,551,615 是(C99起)
float 用于存储单精度浮点数 4字节 约 ±3.4e ±38 (7位有效数字)
double 用于存储双精度浮点数 8字节 约 ±1.7e ±308 (15位有效数字)
long double 用于存储长双精度浮点数 8字节 约 ±1.7e ±308 (15位有效数字)
wchar_t 宽字符类型 2 或 4字节 1宽字符 是(C95起)
char16_t 用于存储16位宽的字符 2字节 1个16位宽的字符 是(C++11起)
char32_t 用于存储32位宽的字符 4字节 1个32位宽的字符 是(C++11起)

注意:存储大小和值范围可能会因编译器或计算机架构的不同而有所不同。

复合数据类型包括数组、结构体、联合体、枚举、类和模板,它们的大小和值范围取决于它们的元素和成员。C++还支持字符串类型std::string,而C语言通常使用字符数组来表示字符串。

数据类型是程序中用来表示数据的形式和范围的分类,不同的数据类型有不同的内存大小和取值范围。C和C++都支持以下几种基本数据类型:

  • 整型(int):用来表示整数,如10-5等。整型有不同的长度,如short(短整型),long(长整型),long long(更长整型)等,长度决定了取值范围。整型也可以有符号(signed)和无符号(unsigned)之分,符号决定了正负范围。例如:
short a = 32767; // a是一个短整型变量,最大值为32767
unsigned short b = 65535; // b是一个无符号短整型变量,最大值为65535
long c = 2147483647; // c是一个长整型变量,最大值为2147483647
unsigned long d = 4294967295; // d是一个无符号长整型变量,最大值为4294967295
long long e = 9223372036854775807; // e是一个更长整型变量,最大值为9223372036854775807
unsigned long long f = 18446744073709551615; // f是一个无符号更长整型变量,最大值为18446744073709551615
  • 浮点型(floatdouble):用来表示小数,如3.14-0.5等。浮点型有不同的精度,如单精度(float),双精度(double),扩展精度(long double)等,精度决定了小数位数。例如:
float a = 3.14f; // a是一个单精度浮点型变量,精度为6~7位小数
double b = 3.1415926; // b是一个双精度浮点型变量,精度为15~16位小数
long double c = 3.14159265358979323846L; // c是一个扩展精度浮点型变量,精度为19~20位小数
  • 字符型(char):用来表示单个字符,如'A''9'等。字符型也可以有符号和无符号之分,符号决定了ASCII码范围。字符型可以用单引号表示字面量,也可以用转义字符表示特殊字符,如换行符(\n),制表符(\t)等。例如:
char a = 'A'; // a是一个字符型变量,值为'A'
unsigned char b = 255; // b是一个无符号字符型变量,值为255对应的ASCII码字符
char c = '\n'; // c是一个字符型变量,值为换行符
  • 布尔型(C中的bool):用来表示真假值,如真(true),假(false)。布尔型只有两个取值,在C中可以用关键字true和false表示,在C中可以用宏定义TRUE和FALSE表示。例如:
bool a = true; // a是一个布尔型变量,值为真
bool b = false; // b是一个布尔型变量,值为假
bool c = (a && b); // c是一个布尔型变量,值为a和b的逻辑与运算结果

除了基本数据类型外,C和C++还支持一些复合数据类型,如数组、结构体、枚举、联合等。复合数据类型是由基本数据类型或其他复合数据类型组合而成的数据类型,它可以表示更复杂的数据结构。我们来看一些复合数据类型的例子。

  • 数组(array):数组是一种由相同类型的元素组成的有序集合,它可以用来存储多个相同类型的数据。数组在内存中占据连续的空间,每个元素都有一个索引来表示其位置,索引从0开始。数组必须在声明时指定其类型和长度,长度不能改变。例如:
int a[10]; // 声明一个长度为10的整型数组a
a[0] = 1; // 给a的第一个元素赋值为1
a[9] = 10; // 给a的最后一个元素赋值为10
int b[3] = {1, 2, 3}; // 声明一个长度为3的整型数组b,并初始化为{1, 2, 3}
char c[] = "Hello"; // 声明一个字符型数组c,并初始化为"Hello",长度为6(包括'\0')
  • 结构体(struct):结构体是一种由不同类型的元素组成的复合数据类型,它可以用来表示一个实体的属性。结构体在内存中占据连续的空间,每个元素都有一个名字来表示其含义,可以用点运算符(.)来访问。结构体必须先定义后使用,定义时要指定结构体的名字和各个元素的类型和名字,可以同时初始化。例如:
struct Student { // 定义一个结构体Student
    int id; // 学号
    char name[20]; // 姓名
    double score; // 成绩
};
struct Student s1; // 声明一个Student类型的变量s1
s1.id = 1001; // 给s1的id赋值为1001
strcpy(s1.name, "人坤"); // 给s1的name赋值为"Alice"
s1.score = 95.5; // 给s1的score赋值为95.5
struct Student s2 = {10028, "坤坤", 28.0}; // 声明并初始化一个Student类型的变量s2
  • 枚举(enum):枚举是一种由一组有名字的常量组成的数据类型,它可以用来表示一些有限的选项或状态。枚举在内存中占据整型大小的空间,每个常量都有一个整数值来表示其顺序,可以用等号赋值运算符(=)来修改。枚举必须先定义后使用,定义时要指定枚举的名字和各个常量的名字,可以同时赋值。例如:
enum Color { // 定义一个枚举Color
    RED, // 红色,值为0
    GREEN, // 绿色,值为1
    BLUE // 蓝色,值为2
};
enum Color c1; // 声明一个Color类型的变量c1
c1 = RED; // 给c1赋值为RED
enum Season { // 定义一个枚举Season,并赋值
    SPRING = 1, // 春天,值为1
    SUMMER = 4, // 夏天,值为4
    AUTUMN = 7, // 秋天,值为7
    WINTER = 10 // 冬天,值为10
};
enum Season s1; // 声明一个Season类型的变量s1
s1 = WINTER; // 给s1赋值为WINTER
  • 联合(union):联合是一种由不同类型的元素组成的复合数据类型,它可以用来表示一个共享内存空间的变量。联合在内存中占据最大元素大小的空间,每个元素都有一个名字来表示其含义,可以用点运算符(.)来访问。联合必须先定义后使用,定义时要指定联合的名字和各个元素的类型和名字,可以同时初始化。联合的特点是同一时间只能存储一个元素的值,如果给一个元素赋值,会覆盖其他元素的值。例如:
union Data { // 定义一个联合Data
    int i; // 整型
    float f; // 浮点型
    char c; // 字符型
};
union Data d1; // 声明一个Data类型的变量d1
d1.i = 10; // 给d1的i赋值为10
d1.f = 3.14; // 给d1的f赋值为3.14,会覆盖i的值
d1.c = 'A'; // 给d1的c赋值为'A',会覆盖f的值
union Data d2 = {20}; // 声明并初始化一个Data类型的变量d2,只能初始化第一个元素
类型转换、强制类型转换和自动类型推断(C++)

在C和C++语言中,类型转换可以分为隐式类型转换和显式类型转换。下面是一个详细的表格:

类型转换 描述 C支持 C++支持
隐式类型转换 当两种不同的数据类型进行混合运算时,编译器会自动进行类型转换。转换规则通常是将"低级别"类型转换为"高级别"类型,以确保不会丢失数据。例如,如果一个 int和一个 double进行运算,int会被转换为 double
C风格类型转换(强制类型转换) 你可以使用强制类型转换运算符 (typename)来显式地转换一个值的类型。例如,double x = (double)3/2;将使得 3 被视为 double类型,从而使得整个除法运算的结果也是 double类型。
static_cast static_cast是C++中最通用的类型转换方式,它可以进行大部分类型的转换,但不能转换掉类型的const、volatile、或者__unaligned属性。例如,double x = static_cast<double>(3)/2;
dynamic_cast dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。在类层次间进行上行转换时,dynamic_caststatic_cast的效果是一样的;在进行下行转换时,dynamic_cast具有类型检查,比 static_cast更安全。
const_cast const_cast主要用于修改类型的const或volatile属性。但是对一个定义为const的变量进行const_cast,然后进行修改,结果是未定义的。
reinterpret_cast reinterpret_cast用于位的简单重新解释。reinterpret_cast是最危险的cast, 它能将任何类型的指针转换为任何其他类型的指针。例如,int* p = reinterpret_cast<int*>(new double(3.14));

注意:类型转换可能会导致数据丢失或溢出,所以在进行类型转换时需要特别注意。

类型转换是程序中将一个数据类型转换为另一个数据类型的过程,有时是必要的,有时是隐含的。类型转换有两种方式:强制类型转换和自动类型推断。

  1. 隐式类型转换:当两种不同的数据类型进行混合运算时,编译器会自动进行类型转换。转换规则通常是将"低级别"类型转换为"高级别"类型,以确保不会丢失数据。
// C/C++
int i = 10;
double d = i;  // 隐式类型转换,将int转换为double
  1. C风格类型转换(强制类型转换):你可以使用强制类型转换运算符 (typename) 来显式地转换一个值的类型。
// C/C++
int i = 3;
double d = (double)i / 2;  // 显式类型转换,将int转换为double
  1. static_caststatic_cast 是C++中最通用的类型转换方式,它可以进行大部分类型的转换,但不能转换掉类型的const、volatile、或者__unaligned属性。
// C++
int i = 3;
double d = static_cast<double>(i) / 2;  // 使用static_cast进行类型转换
  1. dynamic_castdynamic_cast 主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。在类层次间进行上行转换时,dynamic_caststatic_cast 的效果是一样的;在进行下行转换时,dynamic_cast 具有类型检查,比 static_cast 更安全。
// C++
class Base { virtual void dummy() {} };
class Derived: public Base { int a; };
Base* base = new Derived;
Derived* derived = dynamic_cast<Derived*>(base);  // 使用dynamic_cast进行类型转换
  1. const_castconst_cast 主要用于修改类型的const或volatile属性。但是对一个定义为const的变量进行const_cast,然后进行修改,结果是未定义的。
// C++
const int i = 10;
int* p = const_cast<int*>(&i);  // 使用const_cast去掉const属性
//*p = 11;  // 结果是未定义的
  1. reinterpret_castreinterpret_cast 用于位的简单重新解释。reinterpret_cast 是最危险的cast, 它能将任何类型的指针转换为任何其他类型的指针。
// C++
double d = 3.14;
int* p = reinterpret_cast<int*>(&d);  // 使用reinterpret_cast进行类型转换

注意:类型转换可能会导致数据丢失或溢出,所以在进行类型转换时需要特别注意。

相关文章
|
6月前
|
Java API C++
Java JNI开发时常用数据类型与C++中数据类型转换
Java JNI开发时常用数据类型与C++中数据类型转换
249 0
|
3月前
|
Java C# C++
C++ 11新特性之语法甜点1
C++ 11新特性之语法甜点1
37 4
|
3月前
|
编译器 C++ 容器
C++ 11新特性之语法甜点2
C++ 11新特性之语法甜点2
34 1
|
3月前
|
存储 Linux C语言
【C++基础】数据类型详解
这篇文章详细介绍了C++中各种基本数据类型,包括整型、浮点型、字符型、字符串型和布尔型,以及它们的使用方式和范围。
37 4
|
3月前
|
存储 算法 编译器
C++ 11新特性之语法甜点4
C++ 11新特性之语法甜点4
32 0
|
3月前
|
安全 C++ 容器
C++ 11新特性之语法甜点3
C++ 11新特性之语法甜点3
44 0
|
4月前
|
C++
c++学习笔记01 基本知识与数据类型
C++学习笔记,涵盖了C++中的常量定义、数据类型、变量内存大小计算、基本数据类型(整型、实型、字符型、字符串型、布尔型)以及转义字符的使用。
48 4
|
4月前
|
编译器 C++ 容器
C++语言的基本语法
想掌握一门编程语言,第一步就是需要熟悉基本的环境,然后就是最重要的语法知识。 C++ 程序可以定义为对象的集合,这些对象通过调用彼此的方法进行交互。现在让我们简要地看一下什么是类、对象,方法、即时变量。 对象 - 对象具有状态和行为。例如:一只狗的状态 - 颜色、名称、品种,行为 - 摇动、叫唤、吃。对象是类的实例。 类 - 类可以定义为描述对象行为/状态的模板/蓝图。 方法 - 从基本上说,一个方法表示一种行为。一个类可以包含多个方法。可以在方法中写入逻辑、操作数据以及执行所有的动作。 即时变量 - 每个对象都有其独特的即时变量。对象的状态是由这些即时变量的值创建的。 完整关键字
|
5月前
|
Java 编译器 程序员
C++中的语法知识虚继承和虚基类
**C++中的多继承可能导致命名冲突和数据冗余,尤其在菱形继承中。为解决这一问题,C++引入了虚继承(virtual inheritance),确保派生类只保留虚基类的一份实例,消除二义性。虚继承通过`virtual`关键字指定,允许明确访问特定路径上的成员,如`B::m_a`或`C::m_a`。这样,即使基类在继承链中多次出现,也只有一份成员副本,简化了内存布局并避免冲突。虚继承应在需要时提前在继承声明中指定,影响到从虚基类派生的所有后代类。**
|
5月前
|
编译器 C++ 开发者
C++一分钟之-属性(attributes)与属性语法
【7月更文挑战第3天】C++的属性(attributes)自C++11起允许附加编译器指令,如`[[nodiscard]]`和`[[maybe_unused]]`,影响优化和警告。注意属性放置、兼容性和适度使用,以确保代码清晰和可移植。示例展示了如何使用属性来提示编译器处理返回值和未使用变量,以及利用编译器扩展进行自动清理。属性是提升代码质量的工具,但应谨慎使用。
171 13