石家庄建设局官方网站,青海住房建设厅网站,外贸出口营销网站,做农产品交易网站C是一种通用的、静态类型的、跨平台的编程语言。它是在1979年由Bjarne Stroustrup创建的#xff0c;最初是作为C语言的扩展来支持面向对象编程。
C在保留C语言的特性的同时#xff0c;添加了许多其他的功能#xff0c;包括类、对象、继承、多态、模板等。这使得C成为了一种…C是一种通用的、静态类型的、跨平台的编程语言。它是在1979年由Bjarne Stroustrup创建的最初是作为C语言的扩展来支持面向对象编程。
C在保留C语言的特性的同时添加了许多其他的功能包括类、对象、继承、多态、模板等。这使得C成为了一种强大而灵活的编程语言可以用于开发各种类型的应用程序包括系统级软件、嵌入式系统、游戏开发、图形界面等。
C也是一种高效的语言其执行速度接近于C语言因为它允许直接访问硬件和内存并支持底层的操作。
C还具有丰富的标准库提供了许多常用的函数和数据结构可以方便地进行文件操作、输入输出、字符串处理等。
总的来说C是一种功能强大、高效、灵活的编程语言广泛应用于软件开发领域。
在系统的了解C之前我们要了解一些C基础以便我们后面更好的理解其他内容。大家也可以借助这一篇来了解C对C有何变化C对C的扩充-CSDN博客
一.命名空间
1.1同名冲突
当我们在编写程序的时候如果在一个作用域中出现了两个或多个同名的变量或者函数就会发生错误
int main()
{int a 0;//……int a 0;return 0;
}
我们在主函数这个作用域中定义了两个a变量在编译的时候就会报错。这就是同名冲突。
同名冲突是在大型应用软件的设计过程中是非常容易发生的。比如程序员A在头文件codeA中定义了student类和fun函数程序员B在头文件codeB中也定义了student类和fun函数。而当主程序员使用A、B写的功能时要包含其头文件但是当包含之后就会在编译时发生错误因为头文件在编译时会展开这就意味着在一个程序中同时出现了两个studen类和fun函数此时就会导致编译失败因为发生了同名冲突。
1.2命名空间 为了解决这个问题ANSIC增加了命名空间namespace。所谓命名空间实际上就是一个由程序设计者命名的内存区域。程序设计者可以根据需要指定一些有名字的空间作用域把一些全局实体分别放在各个命名空间中从而与其他全局变量实体分割开来。 命名空间的定义格式为
namespace 命名空间名
{//命名空间成员
} 如定义一个名为xiasicheng的命名空间
namespace xiasicheng
{//命名空间成员const int a 10;int a 2;int func(){cout hello endl;}struct student{int age;char name[10];};} 命名空间的作用时建立一些互相分隔的作用域把一些全局实体分隔开来以免产生名字冲突。
在声明一个命名空间时花括号内不仅可以可以包含变量还可以包含一下类型
变量可以初始化常量函数可以是定义也可以是声明结构体类模板命名空间命名空间的嵌套
namespace xiasicheng
{//命名空间成员const int a 10;namespace xiasicheng2{int b 0;}
}
需要注意的是命名空间不会改变变量的生命周期本来是全局变量定义在命名空间中还是全局变量。
1.3命名空间的使用
1.3.1指定命名空间访问 当我们需要使用命名空间中的成员时要用命名空间名和作用于限定符对命名空间成员进行限定以区别不同的命名空间中可能有同名的标识符即
//命名空间名::命名空间中的成员名
cout xiasicheng::a endl; 但是当命名空间名字比较长并且还要多次引用其成员时就会非常不方便。
为此C提供了一些机制能简化使用命名空间中成员的方法
1.3.2使用命名空间的别名
可以为命名空间起一个别名用来代替较长的命名空间名。
如
namespace Television
{int a 0;
}namespace TV Television;//用TV代替Televisionint main()
{cout Television::a endl;cout TV::a endl;return 0;
}
1.3.3使用using将命名空间中某个成员展开
using后面的成员名必须是由命名空间名限定的名字。例如
using TV::a;
它表示在using语句所作用的作用域中可以用TV命名空间中的成员a而且不必再逐个用命名空间名限定了。当我们要再使用变量a时直接调用即可
cout a endl;//相当于cout TV::a endl;
但是要注意在同一作用域中用using声明的不同命名空间的成员不能有同名的成员。
1.3.4使用using namespace展开命名空间
C提供了using namespace 语句来实现一次性展开命名空间一般格式为
using namespace 命名空间名; 当我们利用该语句展开某个命名空间之后该命名空间中的所有成员都可以直接进行访问不必再使用作用于限定符限定或者using语句声明某一个成员。 当是在使用using namespace 和using展开某一个成员时都存在风险所以在项目中时建议使用命名空间名作用于限定符的方式来访问变量。 二.C的输入输出
C有一套自己的输入输出方式我们可以使用cout来实现输出cin实现输入。它们是C的标准输出流和输入流。
int a 0;
cin a;
cout a endl;
因为C是包含C的所以在我们的C程序中也可以使用C语言的输入输出方式但是C的输入输出有一个很好的东西那就是可以自定识别类型。我们不再像C语言那样要进行格式控制我们C直接写入变量名即可不必控制变量的类型cout和cin会自动识别的。
int main()
{int a 0;cin a;scanf(%d, a);cout a endl;printf(%d\n, a);return 0;
}
其实cout和cin也是包含在std这个命名空间中的因为我们再文件开头就展开了std所以我们不再需要进行限定所以cout和cin的使用可以借助std和作用域限定符
std::cin a;
std::cout a endl;
三.缺省参数 缺省参数也叫做有默认参数的函数所以缺省参数是应用在函数模块中的。其含义就是在定义函数时给形参一个默认值当我们调用该函数时如果没有传实参该函数就会使用这个默认值如果传了实参该函数就会使用该实参而屏蔽掉缺省参数。 int MAX(int a 0, int b 0)
{return a b ? a : b;
}
当一个函数有多个形参时其可以分为全缺省半缺省不缺省
全缺省就是其形参每一个都带有默认值传参数时可以只传一个也可以传多个传了就用实参没传的就用缺省值。
半缺省就是只有一部分形参有缺省值当一个函数是半缺省时其带有缺省值的形参必须在形参表列的最右边。
int func(int a, int b, int c 0, int d 0)
{cout a b c d endl;
}
如果缺省值跳跃在传参时就会产生歧义
int func(int a 1, int b, int c 0, int d 0)
{cout a b c d endl;
}int main()
{func(2);return 0;
}
此时2是传给a呢还是b呢所以为了避免该情况的出现带缺省值的形参应在形参表列的最右边。
四.变量的引用
引用reference是C对C的一个重要扩充
4.1引用的概念
在C中变量的“引用”就是变量的别名因此引用又叫别名alias。建立“引用”的作用是为一个变量再起另一个名字以便在需要时可以方便、间接地引用该变量这就是引用名称的由来。当我们给一个变量起了一个别名之后他们两个占用同一块空间。
int a 10;
int b a;//给a取了一个别名ba和b占用同一块内存空间
注意在声明一个别名时必须同时给出初始化。 我们打印a和b的地址可以看到它们的地址相同。 当我们修改其中任意一方时另一方也会发生改变。 4.2引用的特性
4.2.1引用在定义时必须初始化且引用的类型必须和被引用对象的类型相同
int main()
{int a 0;int b a;//正确int c;//没有初始化double d a;//引用类型与被引用类型不同return 0;
}
4.2.2一个变量可以有多个引用
int a 0;
int b a;
int c a;
int d a;
当我们打印它们的地址时它们都指向的是同一块空间 4.2.3引用在初始化后不能再被重新声明为另一个变量的别名
int main()
{int a 0;int b a;//b是a的别名int c 10;b c;//企图让b成为c的别名错误return 0;
}
4.2.4对于引用的初始化可以用一个变量名也可以用另一个引用
int main()
{int a 10;int b a;int c a;//用变量初始化int d b;//用另一个引用初始化return 0;
}
4.3引用作为函数参数
用引用作为函数参数时可以代替传地址的方式使实参改变当函数形参为引用时实参直接传变量也会改变。
void Swap(int a, int b)
{int tmp a;a b;b tmp;
}
void Swap(int* a, int* b)
{int tmp *a;*a *b;*b tmp;
} 我们可以对比引用传参和指针传参的区别引用传参会更加方便如果使用指针的话还要对变量进行解引用。
4.4const引用 const引用可以作为普通变量的别名也可以作为const变量的别名。前者属于权限缩小或者属于权限平移。 int a 0;
const int b a;
此时b不可以改变但是a可以改变。 此时属于权限缩小原来a可写可读b只能读不能写。
const int c 100;
const int d c; 此时c和d都不能改变。此时属于权限平移原来c只可读不可写d也只能读不能写。
需要注意的是权限只能平移或者缩小但不能放大。
const int e -1;
int f e;
e只可读但f作为e的引用可读可写此时权限放大运行会出错。 4.5const引用中的常属性临时变量
double a 1.2;
int b a; a是浮点型而想给其取一个int型的别名。此时会发生隐式转化a会隐式转化为整型储存在临时变量中而临时变量具有常属性只可读但是给其取别名时发生了权限放大所以上面的写法是错误的。 正确的方法是用const引用接收
double c 2.2;
const int d c; 4.6引用和指针的关系
C中引用是引用指针是指针两者相辅相成。
语法概念上引⽤是⼀个变量的取别名不开空间指针是存储⼀个变量地址要开空间。引⽤在定义时必须初始化指针建议初始化但是语法上不是必须的。引⽤在初始化时引⽤⼀个对象后就不能再引⽤其他对象⽽指针可以在不断地改变指向对象。引⽤可以直接访问指向对象指针需要解引⽤才是访问指向对象。sizeof中含义不同引⽤结果为引⽤类型的⼤⼩但指针始终是地址空间所占字节个数(32位平台下 占4个字节64位下是8byte)。指针很容易出现空指针和野指针的问题引⽤很少出现引⽤使⽤起来相对更安全⼀些。 五.重载函数
C中的输入输出语句中用到的和叫做流插入操作符和流提取操作符。而在C语言中它们作为位运算符这叫做运算符重载即一物多用。
而重载函数也叫函数重载也就是一物多用的意思同名函数有着不同的作用。 C允许在同一作用域中用同一函数名定义多个函数这些函数的参数个数和参数类型不相同用来实现不同的功能。这就是函数重载即一个函数名多用 int ADD(int x, int y)
{return x y;
}double ADD(double x, double y)
{return x y;
}
对上面两个函数而言实现了整数相加和浮点数相加的功能当我们调用ADD函数时该函数会根据参数的不同调用不同的函数。这就是函数重载的体现。
但是函数重载的前提是函数的形参表列不同
形参个数不同形参类型不同形参个数和类型都不同形参顺序不同
需要注意的是函数重载跟返回值类型无关返回值不同形参相同的两个函数不能设计为重载函数。
六.inline
inlne是C的一个关键字它可以使一个函数成为内联函数。 调用函数时需要建立函数栈帧这需要时间当一个函数被频繁调用时就会加大时间的消耗导致程序效率降低。C提供了一种提高效率的方法即在编译时将所调用函数的代码嵌入到主调函数中。这种嵌入到主调函数中的函数称为内联函数又称内置函数。 inline int ADD(int x, int y)
{return x y;
}
当我们调用该函数时其就会在调用出展开
int main()
{ADD(1, 2);return 0;
}
//展开
int main()
{return 1 2;return 0;
} 其实inline的出现是为了替代C语言中的宏。因为宏是一种文本替换不进行类型检查不安全。所以C就引入了inline这一关键字。 但是函数是否展开是跟编译器有关的。当你将一个函数定义为inline时编译器会检查你设置的是否合理如果合理编译器就会在调用出展开否则就不展开。 将一个函数定为内联函数的前提是该函数代码量少10行之内且会被频繁调用。 七.nullptr
nullptr是C11引入的一个空指针常量。在C中空指针通常用NULL或0来表示但这种表示方式可能存在一些模糊性和歧义。为了解决这个问题C11引入了nullptr作为一个明确的空指针常量。
nullptr可以被赋值给指针类型的变量表示该指针不指向任何有效的内存地址。使用nullptr可以提高代码的可读性和安全性因为它可以更清晰地表示一个空指针。另外nullptr还可以与其他指针进行比较操作以判断指针是否为空。
示例代码
int* ptr nullptr; // 定义一个指向整型的空指针if (ptr nullptr) {// 检查指针是否为空// 执行相关操作
}总的来说nullptr是C中用于表示空指针的常量它在C11中被引入提高了代码的可读性和安全性。 完