a = & b vs *a = & b — 指针赋值

a = &b vs *a = &b — pointer assignment

我有一个指针和一个变量:

int *a;
int b;

赋值有区别吗

a = &b;

*a = &b;

它们叫什么(比如指针声明之类的)?

类型很重要。

  • a=&b的情况下,分配有效。您正在将一个整数(类型:int *)的地址分配给另一个类型为 int * 的变量,所以这是合法的。

  • *a=&b 的情况下,这是违反约束的(对于赋值运算符,请参阅章节 §6.5.16.1/p1,Constraints,用于Simple assignment),因此不是valid C 语法,因此不需要任何编译符合编译器。为了使其成为有效的 C 语法,我们需要 enforce 一个 typecast,类似于

    *a= (int) &b;
    

    将使它在句法上成为 有效的 C 语句,满足要求的约束。

    即使在那之后,结果也是实现定义的。#note 在这里,您基本上是在尝试分配一个整数的地址(类型:int *) 到另一个 int 类型的变量(*aint 类型)。从指针到整数的转换是实现定义的行为。

    引用 C11,章节 §6.3.2.3,指针

    Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. [....]

[....] And what are they called?

它们都是赋值语句。


注:

考虑到 a 已经指向一个有效的内存位置。否则,取消引用无效指针会自行调用 undefined behavior

第一个没问题,但第二个调用了 UB。 (除非 a 指向某个有效内存)

肯定是有区别的
& 表示指针(从指针可以取值)
*代表价值
a=&b(代表b的等分点)
*a=&b(表示b的等分值)

Helped Tutorial

注意=左右的类型。

&bint *a 也是 int **aint


*有不同的含义有点令人困惑:

int *a; — 这里 * 表示 a 将是一个指针;

*a = ...; — 这里 * 表示我们更改的不是存储在 a 中的地址,而是位于该地址的值。


所以a = &b表示"write the address of b to a",

*a = &b 表示 "write the address of b to *a, i.e. to the address which is stored in a"。


假设我们遇到这种情况:

   Address  Value
 a 0x0001   0x0004
 b 0x0002   70
   0x0003   80
   0x0004   90

目前 a0x0004*a90

如果您这样做 a = &ba 将是 0x0002,而 *a 将是 70

但是如果你做*a = &b,a不会改变,但是*a,即地址0x0004的值会变成0x0002.

一个显着的区别是第二个赋值是错误格式的 C(因为 约束违规):

*a = &b;

error: assignment makes integer from pointer without a cast [-Wint-conversion]

C11 §6.5.4/3,转换运算符:

Conversions that involve pointers, other than where permitted by the constraints of 6.5.16.1, shall be specified by means of an explicit cast.

C89 中引入了显式转换的要求,以禁止在整数和指针类型之间进行隐式转换的不良做法。

此规则的唯一例外是您可以用 0 整数常量分配指针值,它表示空指针常量:

a = 0; // more idiomatically: a = NULL;

给定类型,以下分配是有效的:

 a = &b; // int * = int *
*a =  b; // int   = int

在第二种情况下,a 必须指向有效的内存位置,否则行为未定义。

*a = &b;  // int = int *

违反了约束,编译器会对你大吼大叫。

Is there any difference between assignments

a = &b;

and

*a = &b;  

是的。在第一种情况下,a&bb 的地址)都是 int * 类型。它们是可分配的。
*a = &b 的情况下,*aint 类型,而 &bint * 类型。两种类型都不兼容,&b 的类型未显式转换为 *a 的类型。这是约束违规。也就是说:int 类型不能保存指针对象。唯一能够容纳指针对象的整数类型是 intptr_tuintptr_t

7.20.1.4 能够保存对象指针的整数类型

1 The following type designates a signed integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:

intptr_t  

The following type designates an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:

uintptr_t

These types are optional.


and what are they called (like pointer declaration or something) ?

它们是赋值语句。

首先让我给你解释一下整型变量和指针变量的区别:

(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.

的强制转换

The first, int a = &b; copies the address of the variable "b" to the "a".

The second, int *a = &b; copies the address of the variable "b" to the location "a" points to.

就像所有其他答案已经指出的那样,给定变量 int *aint b:

  • 赋值a = &b有效(并将b的地址赋值给指针a,这样*a就可以用来访问b), 而
  • 赋值 *a = &b 违反约束,因为它试图将 b 的地址分配给 a 指向的整数,如果没有显式强制转换,这是不允许的.

What might be confusing you, 然而,就是变量声明:

int b;
int *a = &b;

有效的,并且与以下内容完全相同:

int b;
int *a;
a = &b;    // not *a = &b!

这非常方便 shorthand,因为您几乎总是希望在声明变量后立即对其进行初始化(如果只是为了确保您不会在初始化之前不小心尝试使用它) .但是当您第一次遇到该语法时可能会感到困惑,因为它 看起来 就像您将 &b 分配给 *a,而实际上它是 a 本身正在使用值 &b 进行初始化。这只是您必须学习的东西:变量初始化与普通赋值不同,即使它看起来相似得令人困惑。