& array == array,结构怎么样?

时间:2016-03-02 13:46:32

标签: c arrays pointers reference

我刚刚开始搞乱结构和指针。

这是我的.h:

#ifndef struct_struct_h
#include <string.h>
#define struct_struct_h



#endif


int count=0;

typedef struct
{
    int num;
    double balance;
    const char * name;
    struct Account * acnt;

} Account;

Account* a = NULL;

Account* new_account(const char * n)
{
    Account *a1 = malloc(sizeof(Account));

    a1->num=++count;
    a1->name = n;
    return a1;
}

这是我的main.c:

#include <stdio.h>
#include <string.h>
#include "struct.h"



int main(int argc, const char * argv[])
{

    // insert code here...
    Account* accounts[2];

    for(int i=0; i<2; i++)
    {
        accounts[i] = (i==0 ? new_account("David") : new_account("Toto") );
    }
    printf("Accounts array address is %i\n",&accounts);

    for(int i=0; i<2;i++)
    {
        printf("Account n°%i is owned by %s \n, its address is %i\n",accounts[i]->num,accounts[i]->name,&accounts[i]);
    }
    printf("There are %i accounts.\n",count);

    return 0;
}

如果我按帐户替换&帐户,我会得到相同的结果:@array,或者是&amp; accounts [0],没关系。

  

帐户数组地址为1606416480

如果我用*帐户替换&帐户,我会得到:

  

帐户数组地址为1063600

第二个输出是:

  

账户n°1归David所有   ,其地址是1606416480

     

帐号n°2归Toto所有   ,其地址是1606416488

实际上这些是账户中包含的@账户指针,这些@在内存中每个自我占用8B。

如果我用帐户[i]替换&amp; accounts [i],那么通过* accounts [i]我得到:

  

账户n°1归David所有   ,其地址是1063600

     

账户n°2由Toto拥有,其地址为1063632

     

账户n°1归David所有   ,其地址是3874

     

帐号n°2归Toto所有   ,其地址是3880

在第一种情况下,我有2个指针,在第二种情况下,我有2个指针。

* STRUCT和STRUCT是不同的,为什么?

2 个答案:

答案 0 :(得分:1)

数组在内部表示为连续的内存范围。在范围的最开始,放置了数组的第一个元素。

如果您的数组的名称与问题<div class="post_nav"> <div class="last">Last</div> <div class="home">&nbsp;</div> <div class="next">Next</div> </div> .post_nav { position: relative; width: 30%; margin: 10px auto; text-align: center; font-family: 'Bitter', Georgia, serif; font-weight: 700; color: #c9c9c9; } .post_nav div { display: inline-block; text-transform: uppercase; padding: 0 20px; } .post_nav .last:before { content: ""; width: 30px; height: 30px; line-height: 20px ; background: url('http://i.imgur.com/BlY1jqF.png') no-repeat -60px 0; float: left; margin: auto 5px; overflow: hidden; } .post_nav .home:before { content: ""; width: 30px; height: 30px; line-height: 30px ; background: url('http://i.imgur.com/BlY1jqF.png') no-repeat -120px 0; float: left; margin: auto 5px; padding: 0; overflow: hidden; } .post_nav .next:after { content: ""; width: 30px; height: 30px; line-height: 30px ; background: url('http://i.imgur.com/BlY1jqF.png') no-repeat -90px 0; float: right; margin: auto 5px; overflow: hidden; } 中的方式相同,那么数组的地址和数组的第一个元素的地址具有相同的值。

如果要考虑你的例子,那么你有

accounts

表达式中的数组(例外情况,例如在sizeof运算符中使用它们)被转换为指向其第一个元素的指针。

因此,表达式Account * accounts[2]; 具有类型accounts和等式

Account **

评估为真。

表达式accounts == &accounts[0] 具有相同的值,因为它是范围的地址,但是具有不同的类型。它的类型是

&accounts

那就是你写的例子

Account * ( * )[2]

然后输出将等于16,因为在运行自己的代码的环境中,指针的大小等于8,而数组由两个指针元素组成。

你可能不会写条件

Account *( *p )[2] = accounts;

printf( "*p = %zu\n", sizeof( *p ) ); 

因为操作数有不同的类型。但是如果你写的话

&accounts == accounts

然后这个条件评估为真。

所以表达式的值

( void *)&accounts == ( void * ) accounts &accountsaccounts彼此相等,是数组占用的内存范围的地址。

对于结构,结构的地址等于其第一个成员的地址。但是,结构类型的对象名称不会隐式转换为指向其第一个成员的指针。

  

如果我用帐户[i]替换&amp; accounts [i],那么通过* accounts [i]我得到:

&accounts[0]给出数组元素的地址。所以你会得到价值

&accounts[i]

值之间的差异等于Account n°1 is owned by David , its address is 1606416480 Account n°2 is owned by Toto , its address is 1606416488 ,即表达式8的值

sizeof( Account * )给出存储在数组元素中的值。它们是结构类型的每个对象的动态alllocated内存的地址。

* accounts [i]是结构类型的对象。由于printf调用中的格式说明符与作为参数传递的对象不对应,因此函数行为未定义。

考虑到要打印指针,您必须使用格式说明符accounts[i]

答案 1 :(得分:0)

TL / DR版本:

数组很特殊,在大多数情况下,数组表达式被视为指向数组第一个元素的指针。 a&a将产生相同的值(数组a的第一个元素的地址),尽管表达式的类型会有所不同。

struct类型(或任何其他聚合类型)不是这种情况。

David Foster Wallace版本:

除非它是sizeof或一元&运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字,表达式为输入&#34; N - T&#34;的元素数组将被转换(&#34;衰减&#34;)到类型为#34的表达式;指向T&#34;的指针,并且表达式的值将是该表达式中第一个元素的地址阵列。

为什么会这样?

首先,让我们看一下数组在内存中的表示方式。鉴于声明

T a[N];

然后你得到的东西看起来像这样:

   +---+
a: |   | a[0]
   +---+
   |   | a[1]
   +---+
    ...
   +---+
   |   | a[N-1]
   +---+

为数组元素留出存储空间,没有别的;没有任何元数据的存储空间,也没有任何指向数组第一个元素的指针。关键的是,除了数组元素之外没有对象arr(换句话说,对象arr 数组元素)。

但是数组下标操作a[i] 定义*(a + i);也就是说,给定地址a,我们从该地址偏移i个元素(不是字节!)并取消引用结果。

但是a是一个数组,而不是指针,那么它是如何工作的呢?

像这样 - 除非它是sizeof或一元&运算符的操作数,或者是用于初始化声明中另一个数组的字符串文字,表达式类型&#34; N - 元素数组T&#34;将被转换(&#34;衰减&#34;)到类型为&#34的表达式;指向T&#34;的指针,并且表达式的值将是第一个元素的地址。阵列 1

因此,在像

这样的代码中
printf( "a = %p\n", (void *) a ); // *always* use `%p` to print pointer values

表达式a不是sizeof或一元&运算符的操作数,因此它被转换为(&#34;衰变&#34;)到类型为&的表达式#34;指向T&#34;的指针,表达式的值是第一个元素的地址。

这里有一个方便的表格来记住其中一些:


  Expression        Type        "Decays" to        Value
  ----------        ----        -----------        -----
           a        T [N]       T *                Address of first element 
          &a        T (*)[N]    n/a                Same value as above, different type
          *a        T           n/a                Value of first element
        a[i]        T           n/a                Value of i'th element
       &a[i]        T *         n/a                Address of i'th element
    sizeof a        size_t      n/a                Number of bytes in array
   sizeof *a        size_t      n/a                Number of bytes in single element
 sizeof a[i]        size_t      n/a                Same as above
   sizeof &a        size_t      n/a                Number of bytes in pointer to array
sizeof &a[i]        size_t      n/a                Number of bytes in pointer to single element

因此,iisizeof a == sizeof (T [N])sizeof *a == sizeof (T)

请注意,表达式sizeof &a == sizeof (T (*)[N])sizeof &a[i] == sizeof (T *)a都会产生相同的(数组的第一个元素的地址),但是表达式的类型会有所不同。 &a&a[0]都有a类型(指向*&a[0]的指针),但T *的类型为T(指向&a的指针-element数组T (*)[N])。这对于指针算术等问题很重要。例如,假设以下代码:

N

T将在T a[N]; T *p = a; T (*ap)[N] = &a; printf( " p = %p, p + 1 = %p\n", (void *) p, (void *) p + 1 ); printf( "ap = %p, ap + 1 = %p\n", (void *) ap, (void *) ap + 1 ); 之后生成数组的下一个元素的地址。 p + 1将在当前数组后面生成下一个 p - ap + 1 元素数组的地址。

N或其他聚合类型没有相应的转换规则,因为在某些上下文与其他上下文中不需要将T表达式视为指针。组件选择运算符structstruct的工作方式与下标运算符的工作方式相同。

<小时/> 1。 C来自早期的编程语言B(go figure),而B存储为&#34;指针&#34;到数组的第一个元素(在B中,指针只是整数偏移)。 Ritchie在开始设计C时保留了B的数组语义,但在他开始添加.类型时遇到了问题。他不想在结构数据中混合数组指针元数据。他通过创建上述转换规则解决了这个问题。