c语言 - a = &b vs *a = &b — 指针赋值



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

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已经指向有效的内存位置。另外,取消引用无效指针会自行调用未定义的行为。

注意=左侧和右侧的类型。

&bint *a也是int **aint


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

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

目前a0x0004*a90.

如果你这样做a = &ba将被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的情况下,*aint型,而&bint *型。Bothe 类型不兼容,并且&b类型未显式转换为*a类型。这是约束冲突。话虽如此:int类型都无法保存指针对象。唯一能够保存指针对象的整数类型是intptr_tuintptr_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 *aint 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的强制。

最新更新