我有一个指针和一个变量:
int *a;
int b;
作业之间是否有任何区别
a = &b;
和
*a = &b;
他们叫什么(如指针声明或其他东西)?
答案 0 :(得分:19)
类型很重要。
如果 a=&b
,则分配有效。您将整数的地址(类型:int *
)分配给另一个类型为int *
的变量,因此这是合法的。
如果是 *a=&b
,则这是违反约束的行为(对于分配运营商,请参阅第6.5.16.1 / p1章,约束, for Simple assignment )因此不是有效的 C语法,因此不需要由任何符合标准的编译器编译。要使其成为有效的C语法,我们需要强制 类型转换,类似
*a= (int) &b;
会使它成为符合所需约束的语法有效 C语句。
在此之后,结果是实现定义的。 #note 在这里,您基本上试图将整数的地址(类型:int *
)分配给另一个变量类型int
(*a
的类型为int
)。从指针到整数的转换是实现定义的行为。
引用C11
,章节§6.3.2.3,指针
任何指针类型都可以转换为整数类型。除非事先指明,否则 结果是实现定义的。如果结果无法以整数类型表示, 行为未定义。 [....]
[....]他们叫什么?
它们都是作业陈述。
注意:
考虑a
已指向有效的内存位置。无论如何,去除反无效指针会自动调用undefined behavior。
答案 1 :(得分:7)
注意=
左侧和右侧的类型。
&b
为int *
,a
也为int *
,*a
为int
。
*
有不同的含义,这有点令人困惑:
int *a;
- 此处*
表示a
将成为指针;
*a = ...;
- 此处*
表示我们不会更改a
中存储的地址,而是更改位于地址的值。
所以a = &b
表示"将b
的地址写入a
",
但*a = &b
表示"将b
的地址写入*a
,即写入a
"中存储的地址。
我们建议我们有这种情况:
Address Value
a 0x0001 0x0004
b 0x0002 70
0x0003 80
0x0004 90
目前a
为0x0004
而*a
为90
。
如果您执行a = &b
,则a
将为0x0002
,*a
将为70
。
但是,如果您执行*a = &b
,则不会更改,但*a
(即地址0x0004
的值)将更改为0x0002
。
答案 2 :(得分:3)
一个值得注意的区别是第二个赋值是格式错误的C(因为约束违规):
*a = &b;
错误:赋值在没有强制转换的情况下从指针生成整数 [-Wint转换]
C11§6.5.4/ 3,演员:
包含指针的转换,除了允许的指令 6.5.16.1的约束,应通过明确规定 投强>
在C89中引入了显式强制转换的要求,以便不允许在整数和指针类型之间进行隐式转换的错误做法。
此规则的唯一例外是您可以使用0
整数常量指定指针值,该常量表示空指针常量:
a = 0; // more idiomatically: a = NULL;
答案 3 :(得分:3)
作业之间是否有任何区别
a = &b;
和
*a = &b;
是。在第一种情况下,a
和&b
(b
的地址)都属于int *
类型。它们是可分配的。
如果是*a = &b
,则*a
的类型为int
,而&b
的类型为int *
。 Bothe类型不兼容,&b
的类型未明确转换为*a
类型。这是违反约束的行为。话虽如此:int
类型不能保存指针对象。能够保存指针对象的唯一整数类型是intptr_t
和uintptr_t
。
1以下类型指定一个带符号的整数类型,其属性是任何指向
void
的有效指针都可以转换为此类型,然后转换回指向void
的指针,结果将比较相等到原始指针:intptr_t
以下类型指定一个无符号整数类型,其属性是指向
void
的任何有效指针都可以转换为此类型,然后转换回指向void
的指针,结果将等于原始指针:uintptr_t
这些类型是可选的。
他们叫什么(像指针声明或什么)?
它们是赋值语句。
答案 4 :(得分:3)
与所有其他答案已经指出的一样,给定变量int *a
和int b
:
a = &b
有效(并将b
的地址指定给指针a
,以便*a
可用于访问b
) ,而*a = &b
是一种约束违规,因为它试图将b
的地址分配给a
指向的整数,如果没有显式强制转换则不允许这样做。< / LI>
What might be confusing you,是变量声明:
int b;
int *a = &b;
有效,并且完全相同:
int b;
int *a;
a = &b; // not *a = &b!
这是一个非常方便的简写,因为你几乎总是想要在声明它时立即初始化变量(如果只是为了确保你在初始化之前不小心尝试使用它)。但是当你第一次遇到这种语法时,它可能会让人感到困惑,因为它看起来就像你将&b
分配给*a
一样,当它实际上a
本身时正在使用值&b
进行初始化。这只是你必须要学习的东西:变量初始化与正常分配不同,即使它看起来容易混淆。
答案 5 :(得分:2)
根据类型,以下分配是有效的:
a = &b; // int * = int *
*a = b; // int = int
在第二种情况下,a
必须指向有效的内存位置,或者行为未定义。
*a = &b; // int = int *
是违反约束的,编译器会对你大喊大叫。
答案 6 :(得分:2)
第一个,int a =&amp; b;将变量“b”的地址复制到 “一”。
第二个,int * a =&amp; b;将变量“b”的地址复制到 位置“a”指向。
答案 7 :(得分:1)
第一个是好的,但第二个调用UB。 (除非a
指向某个有效的内存)
答案 8 :(得分:1)
他们之间确实有不同之处
select
DECODE(SIGN(A.column - to_date((
DECODE('10/01/2011',
'%',to_char(A.column,'mm/dd/yyyy'),'10/01/2011') ),
'mm/dd/yyyy')),
-1, 0,
A.Amount))
from A
表示指针(来自指针,你可以获得值)
Whoops, looks like something went wrong.
2/2
QueryException in Connection.php line 770:
SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: YES) (SQL: select * from `users` where `users`.`id` = 1 limit 1)
代表值
&
(代表b的相等点)
*
(代表b等于b的值)
答案 9 :(得分:1)
首先让我清楚整数变量和指针变量之间的区别:
(1)整数变量(例如: int b ,在这种情况下)用于存储整数的值(长度为4个字节)。 &#39; b&#39;的价值存储在某个内存位置(比如0x00000001)。
(2)指针变量(例如: int * a ,在这种情况下)用于存储整数变量的内存位置。也就是说,在&#39; a&#39;我们可以存储整数变量的地址。指针变量指向的值可以通过使用&#39;取消引用。 *&#39;运营商。所以&#39; a&#39;将有地址和&#39; * a&#39;将具有由a中包含的值(地址)指向的值。
现在回答你的问题:
假设b = 4,b(&amp; b)的地址是0x00000001(十六进制表示法)。
在第一个类型赋值 a =&amp; b 中,变量整数b的地址存储在a中(因为a是指针变量)。现在&#39; a&#39;具有值0x00000001和&#39; * a&#39;将有4个。
在第二类型赋值 * a =&amp; b 中,变量b的地址存储在由a指向的存储单元中,即在0x00000001内存位置将具有值0x00000001本身。现在&#39; a&#39;具有值0x00000001和&#39; * a&#39;也将具有相同的值0x00000001。
答案 10 :(得分:1)
int *a;
int b;
Is there any difference between assignments `a = &b` and `*a = &b`.
T类型的任何变量var
在内存中都有一些位置,其地址由编译器或静态或动态链接器分配。某些变量的地址可以通过&amp; var获得,并且类型为pointer to T
。因此,当您应用&
运算符时,您将该类型嵌套在另一个指针中。 a =&amp; b是正确的。
另一方面,*a=&b
不正确。您尝试在变量* a(具有类型int
)中存储指向变量b(具有类型pointer to int
)的基址的指针。在指针具有64位且int具有32位的体系结构中,这将导致失败。另一方面,在指针和int具有相同长度的体系结构上,如果插入强制转换,这是可能的。编译器不会自动将强制性从int*
插入int
。