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

时间:2017-01-02 09:15:22

标签: c pointers variable-assignment

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

int *a;
int b;

作业之间是否有任何区别

a = &b;

*a = &b;

他们叫什么(如指针声明或其他东西)?

11 个答案:

答案 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)

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

&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 = &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&bb的地址)都属于int *类型。它们是可分配的。
如果是*a = &b,则*a的类型为int,而&b的类型为int *。 Bothe类型不兼容,&b的类型未明确转换为*a类型。这是违反约束的行为。话虽如此:int类型不能保存指针对象。能够保存指针对象的唯一整数类型是intptr_tuintptr_t

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

  

1以下类型指定一个带符号的整数类型,其属性是任何指向void的有效指针都可以转换为此类型,然后转换回指向void的指针,结果将比较相等到原始指针:

intptr_t  
     

以下类型指定一个无符号整数类型,其属性是指向void的任何有效指针都可以转换为此类型,然后转换回指向void的指针,结果将等于原始指针:

uintptr_t
     

这些类型是可选的。

  

他们叫什么(像指针声明或什么)?

它们是赋值语句。

答案 4 :(得分:3)

与所有其他答案已经指出的一样,给定变量int *aint 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的值)

Helped Tutorial

答案 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