C/C++ * & : :: -> .等特殊符号

这篇博客详细介绍了C/C++中一些关键符号的用法,包括*作为乘法运算、注释、指针、取地址运算符&,以及函数参数的传递。同时,讲解了引用&的重要性和不同场景下的应用,如函数传入普通参数、指针参数和引用参数。此外,还提到了其他一些常见的特殊符号,如::的域操作、冒号在位域定义和构造函数初始化列表中的作用,以及->和.的成员访问操作。
部署运行你感兴趣的模型镜像

C/C++中 * 的用法

1>乘法运算

2>注释

3>指针:(最重要)

指针是指向变量的地址
简单的例子分析:

#include <iostream>

using namespace std;

 int main()
 {
 	int a = 3;
 	int *b = &a;
 	cout << "a:" << a << endl;
 	cout << "&a:" << &a << endl;
 	cout << "b:" << b << endl;
 	cout << "*b:" << *b << endl;
 	*b = 10;
 	cout << "a:" << a << endl;
 	cout << "&a:" << &a << endl;
 	cout << "b:" << b << endl;
 	cout << "*b:" << *b << endl;
 }

结果:

分析:
b是a的指针,指向a的地址。(也就是a与b相连,只要修改*b的值,a的值也跟着改动)

 

C/C++中 & 的用法

1>位运算符

a&b

2>逻辑与 &&

if((a==0)&&(b==0)){}

 

3>&取变量地址

先看下面几个简单的例子:

 #include <stdio.h>

int main(void)
{
    int a = 0;
    int *p = &a;
    printf("The value is: %d\n", *p);
    return 0;
}

上面代码中,指针p指向变量a的地址。在C/C++中,每个变量都有其相应的地址,通过在变量标识符前加&符号即可获得变量的地址。

那么我们这么写可以吗?int *p = &0x01000;

这显然不行。因为对于一个数值常量,它是没有地址的。而变量之所以有地址就是因为要有一个存储单元对变量进行标识(当然,变量也可以直接映射到某个寄存器)。

我们再看下面的代码:


#include "stdio.h"

int main(void) 
{ 
    int a = 0; // &a = 0x0012ff60 
    int *p = &*(int*)0x0012ff60; 
    printf("The value is: %d\n", *p); 
    return 0; 
}

 上面代码又是怎么回事呢?

先前已经调查过变量a的地址——0x0012ff60,那么这里的指针p实际上也是指向变量a的地址。

首先,将0x0012ff60作为int*,这时它与&a是等价的。

然后*(int*)0x0012ff60表示取变量a的内容。

最后,&*(int*)0x0012ff60表示再脱去*(int*)0x0012ff60的解引用,相当于又变为(int*)&a。

因此,这里的&与第一个例子中的&是不同的语义。这里的&不是取地址,因为一个*(int*)0x0012ff60不是变量,它是没有地址的。每一个变量标识符在编译期间,编译器会为它们创建一个符号表,其中存放着变量标识符相应的各种属性,如类型、地址标识等。地址标识在连接后即可确定逻辑地址值。简而言之,&作为取地址操作,当且仅当&后面跟着的是变量或函数标识符。所以这里的&表示脱去解引用。

由此我们可以得出:&作为取地址操作时,其行为结果是在编译时就被确定的;而*,解引用操作(或取内容)操作,其行为结果只能在运行时才可被确定

 

再看下面的例子,加深印象:

#include "stdio.h"


int main(void)
{
    int a = 0;
    int *p = &*&*&a;
    printf("The value is: %d\n", *p);
    return 0;
}

 

4>引用 &(最重要)

引用可说把a变量换了一个名字为b即:

&b=a

简单的例子分析:

#include <iostream>

using namespace std;


//引用
int main()
{
	int a = 3;
	int &b = a;
	int c = a;
	cout << "a:" << a << endl;
	cout << "b:" << b << endl;
	cout << "c:" << c << endl;
	b = 10;
	cout << "a:" << a << endl;
	cout << "b:" << b << endl;
	cout << "c:" << c << endl;
	cout << "&a:" << &a << endl;
	cout << "&b:" << &b << endl;
	cout << "&c:" << &c << endl;
}

结果:

分析:
& 引用 :比如说,一个人有多少外号,但都是指这个人,引用也是这样。如果b的值改动了,也就代表了a的值改动了。

(核心)函数的参数

1>函数传入普通参数

//函数传入普通参数
void fun(int a,int b)
{
	int c = 0;
	c = a;
	a = b;
	b = c;
}
int main()
{
	int a = 1;
	int b = 2;
	cout << a << "," << b << endl;
	fun(a, b);//a,b交换
	cout << a << "," << b << endl;
	system("pause");
	return 0;
}

结果:
1,2
1,2
分析:
函数传入的是形参,不会改变main()中a,b的地址,也就是不会改变a,b的值。普通的变量赋值操作,调用期间创建了在find函数范围内的局部变量a,它的值与b相同,展示的依旧是全局变量

2>函数传入指针参数

//函数传入指针参数
void fun(int *a, int *b)
{
	int c = 0;
	c = *a;
	*a = *b;
	*b = c;
}
int main()
{
	int a = 1;
	int b = 2;
	cout << a << "," << b << endl;
	fun(&a, &b);//a,b交换
	cout << a << "," << b << endl;
	system("pause");
	return 0;
}

结果:
1,2
2,1
分析:
函数的参数传入的是指针,即地址。创建了一个新的指向b的整型指针a作为find函数范围内的局部变量,函数中a,b的交换是地址的交换。最后main()中的a,b的值也就改变了。

3>引用传入函数参数(简单–好操作)

//引用传入函数参数
void fun(int &a, int &b)
{
	int c = 0;
	c = a;
	a = b;
	b = c;
}
int main()
{
	int a = 1;
	int b = 2;
	cout << a << "," << b << endl;
	fun(a, b);//a,b交换
	cout << a << "," << b << endl;
	system("pause");
	return 0;
}

结果:
1,2
2,1
分析:
本质上是把main()中的a,b变量 换了个名字,即:函数中的a,b,函数中的a,b地址与main()中的地址是一样的。如果函数中的a,b值改变的,那么main()中的a,b的值也跟着改变。

 

PS 另外其他的一些常见特殊符号

1> ::

(1)表示“域操作符”

比如声明了一个类A,类A里声明了一个成员函数voidf(),但没有在类的声明里给出f的定义,那么在类外定义f时,就要写成voidA::f(),表示这个f()函数是类A的成员函数。例如

	class CA {  
	public:  
	  int ca_var;  
	  int add(int a, int b);  
	  int add(int a);  
	}; 
	  
	//那么在实现这个函数时,必须这样书写:  
	int CA::add(int a, int b)  
	{  
	  return a + b;  
	}  
	  
	//另外,双冒号也常常用于在类变量内部作为当前类实例的元素进行表示,比如:  
	int CA::add(int a)  
	{  
	  return a + ::ca_var;  
	} 
	  
	//表示当前类实例中的变量ca_var。


(2)直接用在全局函数前,表示是全局函数
例:在VC里,你可以在调用API 函数里,在API函数名前加::

(3)表示引用成员函数及变量,作用域成员运算符

例:System::Math::Sqrt() 相当于System.Math.Sqrt() 

2> 冒号(:)

1、位域定义
(1)表示机构内位域的定义(即该变量占几个bit空间)

typedef struct _XXX{

unsigned char a:4;

unsigned char c;

} ; XXX

(2)构造函数后面的冒号起分割作用,是类给成员变量赋值的方法,初始化列表,更适用于成员变量的常量const型。

struct _XXX{

_XXX() : y(0xc0) {}

};

(3) public:和private:后面的冒号,表示后面定义的所有成员都是公有或私有的,直到下一个"public:”或"private:”出现为止。"private:"为默认处理。

(4)类名冒号后面的是用来定义类的继承。

class 派生类名 : 继承方式 基类名

{

派生类的成员

};

继承方式:public、private和protected,默认处理是public。

2、类构造函数(Constructor)的初始化列表
先说下什么叫构造函数吧。所谓构造函数,就是与类同名的函数,它与普通函数的区别在于,它没有返回类型。
在构造函数后面紧跟着冒号加初始化列表,各初始化变量之间以逗号(,)隔开。下面举个例子。
class myClass
{
public :
myClass();// 构造函数,无返回类型,可以有参数列表,这里省去
~myClass();// 析构函数
int a;
const int b;
}

myClass::myClass():a(1),b(1)// 初始化列表
{
}
上面的例子展示了冒号的这个用法,下面对这个用法进行几点说明:
1)初始化列表的作用相当于在构造函数内进行相应成员变量的赋值,但两者是有差别的。
在初始化列表中是对变量进行初始化,而在构造函数内是进行赋值操作。两都的差别在对于像const类型数据的操作上表现得尤为明显。我们知道,const类型的变量必须在定义时进行初始化,而不能对const型的变量进行赋值,因此const类型的成员变量只能(而且必须)在初始化列表中进行初始化,即下面的代码将会出错:
myClass::myClass()
{
a = 1;// 没错,效果相当于在初始化列表中进行初始化
b = 1;// 出错,const变量不能进行赋值操作;
}
2)初始化的顺序与成员变量声名的顺序相同。
先看一下下面的程序:
myClass::myClass():b(1),a(b)
{
}
这样的执行结果a,b各是多少呢?b=1,a=1?不是,b=1而a是个随机数。这一点是相当重要的哦,一般在初始化列表中进行初始化时,初始化的顺序应与声明的顺序保持一致,防止出现不必要的错误。
3)对于继承的类来说,在初始化列表中也可以进行基类的初始化,初始化的顺序是先基类初始化,然后再根据该类自己的变量的声明顺序进行初始化。

3、声明基类。
假设我们重新定义一个类,继承自myClass类。定义方式如下:
class derivedClass : public myClass
{
// 略去
}
这里的冒号起到的就是声名基类的作用,在基类类名前面可以加public/private/protected等标签,用于标识继承的类型,也可以省略,省略的话,用class定义的类默认为private,用struct定义的类默认为public,至于具体各个标签有什么区别这里就不说了。
与初始化列表一样的,这里也可以声名多个基类,各基类之间用逗号(,)隔开。

4、条件语句(? :)
与?构成条件语句,作用相当于if else,如下;
int a,b,c;
a=3;
b=2;
c=a>b?a:b;// 如果a>b成立,则反a赋给c,否则把b赋给c
条件语句的结构为:
条件表达式?表达式1:表达式2
当条件表达式为true时,表达式的值为表达式1的值,否则为表达式2的值。
几点说明:
1)?:可以嵌套,但不推荐使用(难懂),下面的表达式你能看懂啥意思不?
int max = i>j ? i>k ? i : k : j>k ? j : k;
脑袋大了吧,呵呵。
2)?:具有很低的优先级,这个要注意哦,下面的程序执行结果是啥呢?
int i = 3;
int j = 2;
cout << i>j?i:j;// 出错,<<比>具有更高的优先级,执行顺序为 ((cout<<i)>j)?i:j,相当于是比较cout<<i与j的大小,然后根据比较结果决定表达式值为i或j,这显然要出错的,cout<<i的值是cout,不能跟整型数j进行比较。
cout << (i>j)?i:j;//输出1或0,相当于(cout<<(i>j))作为判决条件,来决定表达式的值为i或j,而cout<<(i>j),i>j则输出1否则0,然后再将(cout<<(i>j))作为?:的条件,如果cout正确执行则为1(true),否则为0(false),以此决定表达式值为i或j
cout <<(i>j?i:j);//i>j则输出i,否则输出j,表达式值为true如果cout正确执行,否则为false
更多的关于优先级的问题就不说了。

5、语句标签
通常跟goto配合使用,如:
step1: a = f1();
....
goto step1;
这种作法也不是很推荐,原因在于它破坏了语句的顺序执行,这样的代价大家应该清楚吧。不过存在即为合理嘛,既然它还存在,肯定还是有它的用处有它的好处的,比如说,多层嵌套的退出(会比break continue直观一点吧),也可以避免重复代码之类之类的

6、switch语句中case后。

7、汇编指令模板
这个我也不懂,不班门弄斧了,可以参考一下:http://developer.e800.com.cn/articles/2006/43/1144846933898_1.html
改天学习一下。

3> "->"和"."

实现的功能是一样的,都是访问类的成员变量或成员函数,"."用于普通变量操作,"->"只能用于指针变量操作。如:若a为一指向对象的指针,a->f(s)就表示调用a所指的对象中的成员函数f(s)。

您可能感兴趣的与本文相关的镜像

TensorFlow-v2.9

TensorFlow-v2.9

TensorFlow

TensorFlow 是由Google Brain 团队开发的开源机器学习框架,广泛应用于深度学习研究和生产环境。 它提供了一个灵活的平台,用于构建和训练各种机器学习模型

1&gt;Misc.obj : error LNK2001: 无法解析的外部符号 &quot;void __cdecl operator delete(void *,unsigned __int64)&quot; (??3@YAXPEAX_K@Z) 21:13:14:191 1&gt;AiManager.obj : error LNK2001: 无法解析的外部符号 &quot;void __cdecl operator delete(void *,unsigned __int64)&quot; (??3@YAXPEAX_K@Z) 21:13:14:191 1&gt;CBuffManager.obj : error LNK2001: 无法解析的外部符号 &quot;void __cdecl operator delete(void *,unsigned __int64)&quot; (??3@YAXPEAX_K@Z) 21:13:14:191 1&gt;CObject.obj : error LNK2001: 无法解析的外部符号 &quot;void __cdecl operator delete(void *,unsigned __int64)&quot; (??3@YAXPEAX_K@Z) 21:13:14:191 1&gt;dllmain.obj : error LNK2001: 无法解析的外部符号 &quot;void __cdecl operator delete(void *,unsigned __int64)&quot; (??3@YAXPEAX_K@Z) 21:13:14:191 1&gt;Misc.obj : error LNK2001: 无法解析的外部符号 atexit 21:13:14:191 1&gt;ShellCode.obj : error LNK2001: 无法解析的外部符号 atexit 21:13:14:191 1&gt;AiManager.obj : error LNK2001: 无法解析的外部符号 atexit 21:13:14:191 1&gt;CBuffManager.obj : error LNK2001: 无法解析的外部符号 atexit 21:13:14:191 1&gt;CObject.obj : error LNK2001: 无法解析的外部符号 atexit 21:13:14:191 1&gt;dllmain.obj : error LNK2001: 无法解析的外部符号 atexit 21:13:14:191 1&gt;CBuffManager.obj : error LNK2001: 无法解析的外部符号 _fltused 21:13:14:191 1&gt;dllmain.obj : error LNK2001: 无法解析的外部符号 _fltused 21:13:14:203 1&gt;Misc.obj : error LNK2001: 无法解析的外部符号 _fltused 21:13:14:203 1&gt;Vector.obj : error LNK2001: 无法解析的外部符号 _fltused 21:13:14:203 1&gt;dllmain.obj : error LNK2001: 无法解析的外部符号 &quot;void * __cdecl operator new(unsigned __int64)&quot; (??2@YAPEAX_K@Z) 21:13:14:203 1&gt;dllmain.obj : error LNK2001: 无法解析的外部符号 &quot;void * __cdecl operator new[](unsigned __int64)&quot; (??_U@YAPEAX_K@Z) 21:13:14:203 1&gt;ShellCode.obj : error LNK2001: 无法解析的外部符号 &quot;void * __cdecl operator new[](unsigned __int64)&quot; (??_U@YAPEAX_K@Z) 21:13:14:203 1&gt;dllmain.obj : error LNK2001: 无法解析的外部符号 &quot;void __cdecl operator delete[](void *)&quot; (??_V@YAXPEAX@Z) 21:13:14:203 1&gt;ShellCode.obj : error LNK2001: 无法解析的外部符号 &quot;void __cdecl operator delete[](void *)&quot; (??_V@YAXPEAX@Z) 21:13:14:203 1&gt;dllmain.obj : error LNK2001: 无法解析的外部符号 _Init_thread_header 21:13:14:203 1&gt;dllmain.obj : error LNK2001: 无法解析的外部符号 _Init_thread_footer 21:13:14:203 1&gt;dllmain.obj : error LNK2001: 无法解析的外部符号 __imp_GetAsyncKeyState 21:13:14:203 1&gt;dllmain.obj : error LNK2001: 无法解析的外部符号 __imp_GetForegroundWindow 21:13:14:203 1&gt;dllmain.obj : error LNK2001: 无法解析的外部符号 &quot;void __cdecl std::_Xlength_error(char const *)&quot; (?_Xlength_error@std@@YAXPEBD@Z) 21:13:14:203 1&gt;dllmain.obj : error LNK2001: 无法解析的外部符号 __chkstk 21:13:14:203 1&gt;dllmain.obj : error LNK2001: 无法解析的外部符号 _Init_thread_epoch 21:13:14:203 1&gt;dllmain.obj : error LNK2001: 无法解析的外部符号 &quot;__declspec(dllimport) void (__cdecl* std::_Raise_handler)(class stdext::exception const &amp;)&quot; (__imp_?_Raise_handler@std@@3P6AXAEBVexception@stdext@@@ZEA) 21:13:14:203 1&gt;dllmain.obj : error LNK2001: 无法解析的外部符号 &quot;const type_info::`vftable&#39;&quot; (??_7type_info@@6B@) 21:13:14:203 1&gt;dllmain.obj : error LNK2001: 无法解析的外部符号 _tls_index 21:13:14:203 1&gt;D:\WeGameApps\英雄联盟\Game\hid.dll : fatal error LNK1120: 16 个无法解析的外部命令
最新发布
08-08
#include &lt;iostream&gt; int main() { std::cout &lt;&lt; &quot;Hello MinGW!&quot; &lt;&lt; std::endl; return 0; }正在启动生成... cmd /c chcp 65001&gt;nul &amp;&amp; D:\gongzuo\minGW\mingw64\bin\gcc.exe -fdiagnostics-color=always -g D:\gongzuo\c++study\study1.cc -o D:\gongzuo\c++study\study1.exe C:\Users\hcl\AppData\Local\Temp\ccs5wWxN.o: In function `main&#39;: D:/gongzuo/c++study/study1.cc:3: undefined reference to `std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt;&amp; std::operator&lt;&lt; &lt;std::char_traits&lt;char&gt; &gt;(std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt;&amp;, char const*)&#39; D:/gongzuo/c++study/study1.cc:3: undefined reference to `std::ostream::operator&lt;&lt;(std::ostream&amp; (*)(std::ostream&amp;))&#39; C:\Users\hcl\AppData\Local\Temp\ccs5wWxN.o: In function `__tcf_0&#39;: D:/gongzuo/minGW/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/iostream:74: undefined reference to `std::ios_base::Init::~Init()&#39; C:\Users\hcl\AppData\Local\Temp\ccs5wWxN.o: In function `__static_initialization_and_destruction_0&#39;: D:/gongzuo/minGW/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/iostream:74: undefined reference to `std::ios_base::Init::Init()&#39; C:\Users\hcl\AppData\Local\Temp\ccs5wWxN.o:study1.cc:(.rdata$.refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_[.refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_]+0x0): undefined reference to `std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt;&amp; std::endl&lt;char, std::char_traits&lt;char&gt; &gt;(std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt;&amp;)&#39; C:\Users\hcl\AppData\Local\Temp\ccs5wWxN.o:study1.cc:(.rdata$.refptr._ZSt4cout[.refptr._ZSt4cout]+0x0): undefined reference to `std::cout&#39; collect2.exe: error: ld returned 1 exit status
07-23
g++ src/SymphonyNo1_DataAquisition.o -o build/SymphonyNo1_DataAquisition -pthread -I./inc -I../SymphonyNo1_Lib/Helper/inc -I../SymphonyNo1_Lib/Sym/inc -I../SymphonyNo1_IPC/Interface/inc -I../SymphonyNo1_IPC/PubSub/inc -I../SymphonyNo1_IPC/PushPull/inc -I../SymphonyNo1_Lib/DataAquisition/inc -L../SymphonyNo1_Lib/Helper/build -L../SymphonyNo1_Lib/Sym/build -L../SymphonyNo1_IPC/PubSub/build -L../SymphonyNo1_IPC/PushPull/build -L -lzmq -lhelper -lps -lpp -lsym -std=c++17 -Wall -Wextra /usr/bin/ld: src/SymphonyNo1_DataAquisition.o: in function `DataAquisition::run()&#39;: SymphonyNo1_DataAquisition.cpp:(.text._ZN14DataAquisition3runEv[_ZN14DataAquisition3runEv]+0x45): undefined reference to `ConfigLoader::Load(std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; const&amp;)&#39; /usr/bin/ld: SymphonyNo1_DataAquisition.cpp:(.text._ZN14DataAquisition3runEv[_ZN14DataAquisition3runEv]+0x1d3): undefined reference to `SensorDevice::GetId() const&#39; /usr/bin/ld: src/SymphonyNo1_DataAquisition.o: in function `void __gnu_cxx::new_allocator&lt;SensorDevice&gt;::construct&lt;SensorDevice, SensorConfig const&amp;, std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt;&amp;, std::shared_ptr&lt;intf::SharedData&lt;bool&gt; &gt;&amp;, std::shared_ptr&lt;spdlog::async_logger&gt;&amp;&gt;(SensorDevice*, SensorConfig const&amp;, std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt;&amp;, std::shared_ptr&lt;intf::SharedData&lt;bool&gt; &gt;&amp;, std::shared_ptr&lt;spdlog::async_logger&gt;&amp;)&#39;: SymphonyNo1_DataAquisition.cpp:(.text._ZN9__gnu_cxx13new_allocatorI12SensorDeviceE9constructIS1_JRK12SensorConfigRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERSt10shared_ptrIN4intf10SharedDataIbEEERSE_IN6spdlog12async_loggerEEEEEvPT_DpOT0_[_ZN9__gnu_cxx13new_allocatorI12SensorDeviceE9constructIS1_JRK12SensorConfigRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERSt10shared_ptrIN4intf10SharedDataIbEEERSE_IN6spdlog12async_loggerEEEEEvPT_DpOT0_]+0x116): undefined reference to `SensorDevice::SensorDevic
03-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值