int int& int * int**的区别、联系和用途(一)

1、int;

int是C++关键字,表示整型,其大小是32位有符号整型,表示的范围是-2,147,483,648 到 

2,147,483,647;在声明和定义变量时使用,它表示的意思是所声明或所定义的变量为整型变量。

如果其用于函数参数时,其传递方向为值传递,即只能将实参的值传递给形参,而不能将

形参的值传递给实参。

例如:通过这种方式去进行交换两个数是无法达到目的的。

例子1:

#include<iostream>
using namespace std;            
voidswap1(inta,intb)
{   
     inttmp;   
     tmp = a;    
     a = b;    
     b = tmp;    
 }   
 int main(){   
     inta = 1;    
     intb = 2;    
     swap1(a, b);    
     cout<<"a = "<<a<<endl;   
     cout<<"b = "<<b<<endl;   
     system("pause");   
     return0;   
 }

结果为:a=1
b=2
因为传递的方式为值传递(单向传递);
2、int&;
这里的&不是取地址符号,而是引用符号,引用是C++对C的一个重要补充。变量的引用就是
变量的别名,讲的通俗一点就是另外一个名字,比如:“张三这个人在家里,老爸老妈叫他
三娃子,那么这个三娃子就是指张三这个人,如果叫张三去做某事,就是叫三娃子去做某事,
这两个名字指的是同一个人。”同样可以理解如果变量b是变量a的引用 那么无论a,b中任
何一个值改变,另外一个也相应的改变,在声明一个引用时,必须同时使之初始化,即声
明它代表哪一个变量。请注意:由于引用不是独立的变量,编译系统不给它单独分配存
储单元,因此在建立引用时只有声明没有定义,只是声明它与原有的某一变量的关系。
在声明一个变量的引用后,在本函数执行期间,该引用一直与其代表的变量相联系,不能
再作为其他变量的别名。说得简单点:张三和三娃子是指同一个人,不能李四也叫三娃子,
如果可以这样,叫三娃子去做什么,是叫李四呢还是张三呢,这就会乱套了。所以在C++中
一个引用变量只能对应一个原始的变量,不能对应两个或多个原始的变量;
下面简单说明引用:
a)声明引用时必须指定它代表的是哪一个变量,即对它初始化。
int &a=b;这样是声明a是变量b的引用
如果是int &a;这样就是错的,没有指定a代表哪一个变量。
b)引用与其所代表的变量共享同一内存单元,系统并不为引用另外分配存储单元;
这个应该好理解;就像前面所说的,张三和三娃子都是同一个人,三娃子只是张三的别名。
因此,对于 int &a=b;这个例子来说,要输出a和b 的地址,肯定是相同的。
c)怎样区分&是引用还是取地址符呢?方法是:判断&a这样的形式前是否有类型符即
int &a=b;如果有类型符(int)则是引用,否则是取地址运算符。
d)对引用的初始化,可以是一个变量名,也可以是另一个引用。
换句话说:张三的别名可以是三娃子,三小子……及其他多个别名
而三娃子也可以有其他的别名,比如说:老三,小三等
用程序可以这样:
int a=1; //这里是定义一个整形变量
int &b=a;//声明b是整型变量a的别名
int &c=b;//声明c是整型引用变量b的别名
int &d=a;//声明d是整型变量a的别名
e)引用初始化后不能再被重新声明为另一变量的别名
即三娃子既然是指张三这个人,就不能让其他人也叫三娃子
即一个别名只能对应一个原始变量,但是一个原始变量可以有多个别名,而且别名也可以
由自己的别名。

C++中增加引用主要是作为函数参数,进行数据传递的功能;
我们知道如果用变量名作为实参,其传递方向是单向的,而用引用作为实参其传递方向
是双向的;
也许你会问,在c语言中不是有指针吗,用指针进行参数传递不也是双向的吗?其实其
本质上也是值传递,只不过是将变量的地址传给指针,通过指针获取变量的值,这样做
虽能得到结果,但通过指针运算符去访问有关变量,比较麻烦。
下面分析一下使用引用和使用指针变量作为函数形参的不同(以例子1中的swap函数为例):
1、如果使用引用,则不必在swap函数设立指针变量,指针变量要另外开辟内存单元,其
内容是地址。而引用不是一个独立的变量,并不占用内存单元
2、在main函数中调用swap函数时实参不必再变量名前加&以表示地址,系统传递的是
实参的地址不是实参的值。
3、使用指针变量时,为了表示指针变量所指向的变量,必须使用指针运算符*,而使用
引用时,引用就代表该变量,不必使用指针运算符*;
4、用引用完成的工作,用指针也能完成。但引用比指针的使用直观、方便,直截了当,
不必“兜圈子”,容易理解。有些过去只能用指针来处理的问题,现在可以用引用来代替,
从而降低了程序设计的难度。
对引用进一步说明:
1、不能建立void类型的引用。
因为任何实际存在的变量都是属于非void类型的,void的含义是无类型或空类型,
void只是在语法上相当于一个类型而已。
2、不能建立引用的数组。
如:char c[6]="hello";
char &rc=c;//错误
因为数组名是数组首元素的地址,本身不是一个占有存储空间的变量。
3、可以将变量的引用的地址赋给一个指针,此时指针指向的是原来的变量。
这句话可以这样说:将引用变量的地址赋给一个指针,此时指针指向的是引用变量,
相当于指向原来的变量
int a=2;
int &b=a;//这个声明语句中的&是一个引用
int *p=&b;//这个指针初始化语句中的&是取地址运算符
上面一行等价于 int *p=&a;
但是不能定义指向引用类型的指针变量,不能写成
int & *p=&a;//企图定义指向引用类型的指针变量p,错误
因为引用不是一种独立的数据类型,因此不能建立指向引用类型的指针变量。
4、可以建立指针变量的引用如
int i=5;
int *p=&i;
int * &pt=p;//建立指针变量p的引用pt
引用变量pt代表一个int *类型的数据对象(即指针变量)
5、可以用const对引用加以限定,不允许直接改变该引用的值,但是可以改变原
变量的值去改变引用的值;
int i=5;
const int &a=i;
a=3;//错误,因为引用a是const int 类型不能直接改变引用的值
但是可以这样修改:
i=3;
此时输出i和a都是3
6、可以用常量或表达式对引用进行初始化,但此时必须用const作声明。
int i=5;
const int &a=i+1;
此时编译系统是这样处理的:生成一个临时变量,用来存放该表达式的值,引用是
该临时变量的别名、系统将“const int &a=i+1;”转换为
int temp=i+1;
const int &a=temp;
临时变量是在内部实现的,用户不能访问临时变量;
用这种办法不仅可以用表达式对引用进行初始化,还可以用不同类型的变量对之
初始化;如
double d=3.1415926;
const int &a=d;
以上等价为:
double d=3.1415926;
int temp=d;
const int &a=temp;
如果在上面不用const则会发生错误
double d=3.1415926;
int &a=d;//未加const,错误
为什么?因为如果可以这样做,那么修改引用a的值(如a=3.56),则临时变量temp的值也
变为3.56,即修改了临时变量temp的值,但不能修改变量d的值,这往往不是用户所希望
的,即存在二义性。与其允许修改引用的值而不能实现用户的目的,还不如不允许修改
引用的值。这就是C++规定对这类引用必须加const的原因。


<think>我们正在讨论C语言中的指针声明初始化问题。用户的问题是:判断`int *ii=j;``int *ii=&j;`哪个语句正确。 首先,回顾下指针的基本概念: - 指针是种变量,用于存储内存地址。 - 声明指针时,使用`*`符号表示该变量是指针类型。 - 初始化指针时,应该将个内存地址赋给指针变量。 现在,分析两个语句: 1. `int *ii = j;` - 这里,`j`是个变量。如果`j`是个整型变量(例如`int j;`),那么`j`的值是个整数,而不是个地址。因此,将个整数值直接赋给指针变量`ii`是不正确的(除非这个整数是个有效的地址,但通常我们不会这样做,而且编译器会给出警告)。 - 如果`j`是个指针变量(例如`int *j;`),那么`j`的值是个地址,这样赋值是合法的,但要注意类型匹配(即`ii``j`应该指向相同类型的数据)。 2. `int *ii = &j;` - 这里,`&j`表示取变量`j`的地址。无论`j`是什么类型的变量(只要它是个变量),`&j`就是个地址。因此,将地址赋给指针变量`ii`是正确的。 但是,我们需要考虑上下文: - 如果`j`是个整型变量(例如`int j;`),那么: - `int *ii = j;` 不正确,因为`j`是整数值,不是地址。 - `int *ii = &j;` 正确,因为`&j`是`j`的地址,可以赋给整型指针`ii`。 - 如果`j`本身就是个指针(例如`int *j;`),那么: - `int *ii = j;` 正确,因为`j`是指针,它的值是个地址,可以赋给另个指针`ii`(注意:两个指针指向同类型)。 - `int *ii = &j;` 也是合法的,但这里`&j`是个指向指针的指针(即`int **`类型),而`ii`是`int *`类型,所以类型不匹配,编译器会报错。 因此,问题在于用户没有提供`j`的类型。在般情况下,我们假设`j`是个普通的整型变量(这是最常见的情况),那么: - `int *ii = j;` 是错误的,因为不能将整数赋给指针(除非进行强制类型转换,但这样通常是不安全的)。 - `int *ii = &j;` 是正确的,因为将整型变量的地址赋给整型指针是正确的。 另外,根据引用[2]中的例子:`int *p=0;`相当于`int *p; p=0;`,这里0是个特殊的地址(空指针),所以是允许的。但如果是`int *p=j;`,而`j`是个非零整数,那么就会产生个警告,因为将整数赋给指针而没有强制类型转换。 引用[4]引用[5]也说明了指针的声明初始化:`int *p = &a;`是正确的,因为`&a`是地址。 所以,结论是: - 在`j`是整型变量的情况下,`int *ii = &j;`是正确的,而`int *ii = j;`是错误的。 - 如果`j`是指针,那么`int *ii = j;`是正确的,而`int *ii = &j;`是错误的(因为类型不匹配)。 由于用户没有说明`j`的类型,我们只能假设典型情况(`j`是整型变量),因此通常认为`int *ii = &j;`是正确的。 为了严谨,我们可以在回答中说明两种情况。 根据引用[1]中提到的:`int *p = a;`只有在`a`是数组名时才成立(因为数组名代表首地址)。同理,如果`j`是数组名,那么`int *ii = j;`也是正确的(因为数组名在表达式中会转换为首元素的地址)。但数组名的情况比较特殊,用户的问题中变量名为`j`,所以通常不是数组名(除非有定义)。 因此,在大多数情况下,我们使用`int *ii = &j;`来将指针指向个整型变量`j`。 总结: - 如果`j`是个整型变量,则`int *ii = &j;`正确,`int *ii = j;`错误。 - 如果`j`是个指针(指向整型的指针),则`int *ii = j;`正确,而`int *ii = &j;`错误(因为类型不匹配,需要`int **ii = &j;`)。 由于用户的问题中两个语句都没有上下文,我们只能分别解释。但用户的问题是“哪个语句正确”,所以我们需要给出条件。 在C语言中,声明指针变量并初始化时,通常我们期望指针指向个同类型变量的地址,所以最常用的正确形式是`int *ii = &j;`(当`j`是整型变量时)。 另外,引用[2]中提到了`int *p=0;`是合法的,因为0可以表示空指针常量。但`int *ii=j;`如果`j`不是0,且不是地址值,则非法。 因此,在回答中,我们要强调:没有上下文的情况下,无法绝对判断,但按照常见用法,`int *ii = &j;`是正确的(当`j`是整型变量时),而`int *ii = j;`只有在`j`是个地址值(比如指针变量或者数组名)时才正确。 为了回答清晰,我们可以这样说: - `int *ii = &j;` 在大多数情况下(当`j`是个整型变量时)是正确的。 - `int *ii = j;` 只有在`j`是个地址值(比如个指针或者数组名)时才正确,否则会导致类型不匹配。 因此,如果用户的问题是基于`j`是个普通的整型变量,那么只有`int *ii = &j;`正确。 最后,我们生成相关问题。 </think>### C语言中指针初始化语句的分析 在C语言中,`int *ii = &j;`是正确的语句,而`int *ii = j;`**通常不正确**(除非特定上下文)。以下是详细分析: #### 1. **`int *ii = &j;`(正确写法)** ```c int j = 10; // 定义整型变量j int *ii = &j; // 正确:ii指向j的内存地址 ``` - **原理**: - `&`是取址运算符,`&j`获取变量`j`的地址 - 指针`ii`存储的是地址值(如`0x7ffc3a8f`) - 符合指针定义:`int*`类型变量必须存储内存地址[^4][^5] - **内存表示**: ``` j (地址0x1000) → | 10 | ii (地址0x2000) → | 0x1000 | // 存储j的地址 ``` #### 2. **`int *ii = j;`(错误写法)** ```c int j = 10; int *ii = j; // 错误:将整数值赋给指针 ``` - **错误原因**: - `j`是整数值(如10),不是内存地址 - 指针`ii`被错误赋值为整数,违反类型安全规则 - 编译器通常发出警告:`warning: initialization of 'int *' from 'int&#39; makes pointer from integer without a cast`[^2] - **危险后果**: - 若`j`值恰好是有效内存地址(如`0x1000`),程序可能意外修改该地址数据 - 若`j`值不是合法地址(如10),访问`*ii`会导致段错误(Segmentation Fault)[^2] #### 3. **特例场景分析** 极少数情况下`int *ii = j;`可能合法: - **当`j`是指针类型**: ```c int k = 10; int *j = &k; // j是指针 int *ii = j; // 合法:指针间赋值 ``` - **当`j`是数组名**: ```c int j[5] = {0}; int *ii = j; // 合法:数组名自动转为首元素地址[^1] ``` 但在大多数场景(`j`为普通整型变量时),此写法是错误的。 ### 正确指针初始化的关键点 1. **类型匹配**: - 左值:`int*`(指针类型) - 右值:必须为地址(`&variable` 或 其他指针) 2. **初始化图示**: ```c int a = 10; // 正确方式 int *p1 = &a; // p1 → a // 错误方式 int *p2 = a; // p2 → 内存地址0x0000000A(危险!) ``` ### 总结对比 | 语句 | 正确性 | 适用场景 | 风险 | |------|--------|----------|------| | `int *ii = &j;` | ✅ 正确 | `j`是普通变量 | 无 | | `int *ii = j;` | ❌ 通常错误 | 仅当`j`是指针或数组名时 | 内存访问错误 | > 💡 最佳实践:始终用取址运算符`&`初始化指针,除非明确知道右值是指针类型
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值