我有一个指针和一个变量:
int *a;
int b;
作业之间有什么区别吗
a = &b;
和
*a = &b;
它们叫什么(比如指针声明什么的)?
类型很重要。
-
在
a=&b
的情况下,赋值有效。您正在将整数(类型:int *
)的地址分配给另一个类型为int *
的变量,因此这是合法的。 -
在
*a=&b
的情况下,这是一个约束冲突(对于赋值运算符,请参阅章节 §6.5.16.1/p1,约束,对于简单赋值),因此不是有效的C 语法,因此不需要由任何符合要求的编译器编译。要使其成为有效的 C 语法,我们需要强制执行类型转换,例如*a= (int) &b;
将使其成为满足所需约束的语法上有效的C 语句。
甚至,在那之后,结果是定义实现。#note在这里,您基本上是尝试将整数(类型:
int *
)的地址分配给另一个类型为int
的变量(*a
类型为int
)。从指针到整数的转换是实现定义的行为。引用
C11
,第 §6.3.2.3 章,指针任何指针类型都可以转换为整数类型。除非前面指定, 结果是实现定义的。如果结果无法以整数类型表示, 行为未定义。[....]
[....]他们叫什么?
它们都是赋值语句。
注意:
考虑到a
已经指向有效的内存位置。另外,取消引用无效指针会自行调用未定义的行为。
注意=
左侧和右侧的类型。
&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不会改变,但*a
,即地址0x0004
的值,会变成0x0002
。
给定类型,以下赋值将有效:
a = &b; // int * = int *
*a = b; // int = int
在第二种情况下,a
必须指向有效的内存位置,否则行为是未定义的。
*a = &b; // int = int *
是约束冲突,编译器会对你大喊大叫。
作业之间有什么区别吗
a = &b;
和
*a = &b;
是的。在第一种情况下,a
和&b
(b
的地址)都是类型int *
。它们是可分配的。
在*a = &b
的情况下,*a
是int
型,而&b
是int *
型。Bothe 类型不兼容,并且&b
类型未显式转换为*a
类型。这是约束冲突。话虽如此:int
类型都无法保存指针对象。唯一能够保存指针对象的整数类型是intptr_t
和uintptr_t
。
7.20.1.4 能够保存对象指针的整数类型
1 以下类型指定一个有符号整数类型,其属性是指向
void
的任何有效指针都可以转换为此类型,然后转换回指向void
的指针,结果将与原始指针相等:intptr_t
以下类型指定一个无符号整数类型,其属性是指向
void
的任何有效指针都可以转换为此类型,然后转换回指向void
的指针,结果将与原始指针相等:uintptr_t
这些类型是可选的。
它们叫什么(比如指针声明什么的)?
它们是赋值语句。
一个值得注意的区别是第二个赋值是格式不正确的 C(由于违反约束):
*a = &b;
错误:赋值从指针生成整数而不进行强制转换 [-温特转换]
C11 §6.5.4/3, 强制转换运算符:
涉及指针的转换,除非 6.5.16.1的约束,应通过明确的方式指定 演员表。
显式强制转换的要求是在 C89 中引入的,以禁止在整数和指针类型之间进行隐式转换的不良做法。
此规则的唯一例外是可以使用整数常量分配指针值0
整数常量,该常量表示空指针常量:
a = 0; // more idiomatically: a = NULL;
像所有其他答案已经指出的那样,给定变量int *a
和int b
:
- 赋值
a = &b
是有效的(并将b
的地址分配给指针a
,以便*a
可以用来访问b
),而 - 赋值
*a = &b
是违反约束的,因为它试图将b
的地址分配给a
指向的整数,如果没有显式强制转换,这是不允许的。
但是,可能让您感到困惑的是,变量声明:
int b;
int *a = &b;
有效,并且执行与以下完全相同的操作:
int b;
int *a;
a = &b; // not *a = &b!
这是一个非常方便的速记,因为你几乎总是想在声明一个变量后立即初始化它(如果只是为了确保你不会在初始化之前意外地尝试使用它)。 但是当您第一次遇到该语法时可能会令人困惑,因为它看起来好像您正在将&b
分配给*a
,而实际上a
本身正在使用值&b
进行初始化。 这只是你必须学习的东西:变量初始化与普通赋值不同,即使它看起来令人困惑地相似。
第一个,int a = &b; 将变量 "b" 的地址复制到 "一"。
第二个,int *a = &b; 将变量 "b" 的地址复制到 位置"A"指向。
第一个是可以的,但第二个调用 UB。(除非a
指向某个有效内存)
当然它们之间存在
差异&
表示指针(从指针您可以获得值)*
表示值a=&b
(表示 b 的相等点)*a=&b
(表示值 b 的相等点)
帮助教程
首先让我澄清整数变量和指针变量之间的区别:
(1)整数变量(例如:int b,在这种情况下)用于存储整数(长度为4字节)的值。"b"的值存储在某个内存位置(例如0x00000001)。
(2)指针变量(例如:int * a,在这种情况下)用于存储整数变量的内存位置。也就是说,在"a"中,我们可以存储整数变量的地址。指针变量指向的值可以使用 ' * ' 运算符取消引用。因此,"a"将具有地址,而"*a"将具有a中包含的值(地址)所指向的值。
现在回答您的问题:
假设b = 4,b(&b)的地址是0x00000001(十六进制表示法)。
在第一个类型赋值 a= &b 中,变量整数 b 的地址存储在 a 中(因为 a 是指针变量)。现在 'a' 的值为 0x00000001,而 '*a ' 将有 4。
在第二种类型赋值*a = &b 中,变量 b 的地址存储在 a 指向的内存位置,即0x00000001内存位置本身0x00000001具有值。现在 'a' 具有值 0x00000001 和 '*a ' 也将具有相同的值0x00000001。
int *a;
int b;
Is there any difference between assignments `a = &b` and `*a = &b`.
任何 T 类型的变量var
在内存中都有某个位置,其地址由编译器或静态或动态链接器分配。一些变量的地址可以通过 &var 获得,并且类型为pointer to T
。 因此,当您应用&
运算符时,会将类型嵌套在另一个指针中。 a=&b 是正确的。
另一方面,*a=&b
是不正确的。 您尝试在变量 *a(类型为int
)中存储指向变量 b(类型为pointer to int
)的基址的指针。 在指针有 64 位而 int 有 32 位的体系结构中,这将导致失败。 另一方面,在指针和 int 具有相同长度的体系结构上,如果插入强制转换,这是可能的。编译器不会自动插入从int*
到int
的强制。