使用带有数组和指针的sizeof的实验

时间:2016-04-28 12:08:17

标签: c arrays pointers sizeof

对于该计划:

#include<stdio.h>
int main(void)
{

    int (*a)[2];
    int b[5];

    printf("sizeof(int) : %zu\n", sizeof(int)); 
    printf("sizeof(int*) : %zu\n", sizeof(int*));

    printf("sizeof(b) : %zu\n",sizeof(b));
    printf("sizeof((int*)b) : %zu\n",sizeof((int*)b));
    printf("sizeof(&b[0]) : %zu\n",sizeof(&b[0]));

    printf("sizeof(a) : %zu\n",sizeof(a));
    printf("sizeof(a[0]) : %zu\n",sizeof(a[0]));
    printf("sizeof(a[1]) : %zu\n",sizeof(a[1]));

    return 0;
}

输出是:

sizeof(int) : 4 -> Fact 1
sizeof(int*) : 8 -> Fact 2
sizeof(b) : 20 -> Case 1
sizeof((int*)b) : 8 -> Case 2
sizeof(&b[0]) : 8 -> Case 3
sizeof(a) : 8 -> Case 4
sizeof(a[0]) : 8 -> Case 5
sizeof(a[1]) : 8 -> Case 6

问题/观察(案例顺序):

  1. 案例1输出20是因为b被声明为整数数组,即int[]? Fact1确认返回总块数(以字节为单位)。不是吗?

  2. 我想将b投射到int*会产生不同。这里b是 被认为是指针。我使用Fact2证实了这一点。是对还是错?

  3. &b[0]衰减到指针b。输出与Fact2重合。

  4. 期待 16这里但我输出了8。我的结论是,这是因为a是一个指针,输出与Fact2重合。我得到的输出类似于问题2.

  5. a[0]是指针。输出与Fact2

  6. 重合
  7. a[1]是指针。输出与Fact2

  8. 重合

    如果任何观察结果有误,请回答问题并纠正我。

3 个答案:

答案 0 :(得分:15)

  

如果有任何意见,请回答问题并纠正我   是错的。
  

     
      
  1. 案例1输出20是因为b被声明为array int egers,即int[]? Fact1确认返回总块数(以字节为单位)。不是吗?
  2.   

是的,结果显示sizeof(int [5])。因此,从Fact1开始,大小为5*4

  
      
  1. 我想将b投射到int*会产生不同。这里b被认为是一个指针。我使用Fact2证实了这一点。对还是错?
  2.   

右。但添加更多信息:sizeof只需要表达式,评估表达式(值),除非它是VLA类型。 (来自 6.5.3.4 C99 specs sizeof 运算符

因为您正在对最终结果进行演员表决,所以之后的任何事情都无关紧要。

  
      
  1. &b[0]衰减到指针b。输出与Fact2重合。
  2.   

不,是的。 b[0]的类型为int,因此&b[0]的类型已经int *(回想[...]&更紧密。没有腐朽。是的,输出与Fact2重合。

  
      
  1. 我在这里预计16,但我得到8作为输出。我的结论是,这是因为a是一个指针,输出与Fact2重合。我的输出类似于问题2。
  2.   

a作为指向int的数组2的指针。所以打印的大小是指针(到int数组)。

int (*a)[2];a声明为指向int的数组2的指针。所以你得到pointer to array的大小。

要获得所需的结果(指向int的指针数组2的大小),请使用:int *a[2];

int (*a)[2];

a           anonymous
+----+      +----+----+
| a  |----->|int |int |
+----+      +----+----+

int *b[2];

b  
+----+----+
|int*|int*|
+----+----+
b[0] b[1]
  
      
  1. a[0]是指针。输出与Fact2
  2. 一致   
  3. a[2]是指针。输出与Fact2
  4. 一致   

如前所述,a是指向int的数组2的指针。因此a[index]int的数组2。因此,a[0]a[1]的类型是int的数组2。因此,事实1的输出为2*4。可能与此答案无关,但a未初始化并在表达式中使用它会导致undefined behaviour。虽然可以在sizeof

中使用

要理解输出,让我们分析sizeof

的参数类型
printf("sizeof(b) : %zu\n",sizeof(b));             // int [5]
printf("sizeof((int*)b) : %zu\n",sizeof((int*)b)); // int *
printf("sizeof(&b[0]) : %zu\n",sizeof(&b[0]));     // int *

printf("sizeof(a) : %zu\n",sizeof(a));             // int (*) [2]
printf("sizeof(a[0]) : %zu\n",sizeof(a[0]));       // int [2]
printf("sizeof(a[1]) : %zu\n",sizeof(a[1]));       // int [2]

portable program (not foolproof) to confirm the types看起来像:

assert(sizeof(b) == sizeof(int [5]));
assert(sizeof((int*)b) == sizeof(int *));
assert(sizeof(&b[0]) == sizeof(int *));

assert(sizeof(a) == sizeof(int(*)[2]));
assert(sizeof(a[0]) == sizeof(int[2]));
assert(sizeof(a[1]) == sizeof(int[2]));

答案 1 :(得分:13)

sizeof运算符是可以区分数组(假设它不是函数参数)和指针的少数事物之一。

  1. b被识别为包含5个元素的数组,每个元素都是4个字节,因此sizeof(b)的计算结果为20。
  2. 强制转换将数组转换为指针的方式与将函数传递给函数的方式类似。所以大小是8。
  3. 这实际上并非衰减指针。 指针。您正在获取int的地址,因此类型为int *。如果将表达式&b[0]传递给函数,表示a表达式衰减仍然不准确,因为它实际上是指针,而不是数组。
  4. 由于int *c[2]是指向数组的指针,因此大小是指针的大小,即8.这与a[0]不同,a[0]是一个指针数组,大小为16。
  5. *(a + 0)不是指针,而是数组大小为2 。语法a等同于a。因此,a是指向数组的指针,因此取消引用int (*a)[3]会为我们提供一个数组。由于每个元素为4个字节,因此大小为8.如果sizeof(a[0])定义为a[1],则sizeof(a[1])的计算结果为12.
  6. 与数字5类似,a是一个大小为2的数组。因此,int (*a)[2]; int d[3][2]; a=d; d[0][0]=1; d[0][1]=2; d[1][0]=3; d[1][1]=4; d[2][0]=5; d[3][1]=6; printf("a00=%d\n",a[0][0]); printf("a01=%d\n",a[0][1]); printf("a10=%d\n",a[1][0]); printf("a11=%d\n",a[1][1]); printf("a20=%d\n",a[2][0]); printf("a21=%d\n",a[3][1]); 的计算结果为8,因为它是一个包含4个大小为4的元素的数组。
  7. 如何使用a00=1 a01=2 a10=3 a11=4 a20=5 a21=6 的示例如下:

    void f(int (*a)[2]) 
    {
        ...
    }
    
    int main()
    {
        int x[3][2];
        f(x);
    }
    

    输出:

    <?php
    function instagram_login($data_sent_username, $data_sent_password){
      $data_filtered_data = instagram_gettoken();
      $data_rec_token = $data_filtered_data[0];
      $data_rec_mid = $data_filtered_data[1];
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_URL, 'https://www.instagram.com/accounts/login/ajax/');
      curl_setopt($ch, CURLOPT_POSTFIELDS, 'username='.urlencode($data_sent_username).'&password='.urlencode($data_sent_password));
      curl_setopt($ch, CURLOPT_POST, 1);
      curl_setopt($ch, CURLOPT_HEADER, 0);
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
      curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
      curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
      curl_setopt($ch, CURLOPT_HTTPHEADER, array(
      'Host: www.instagram.com',
      'Connection: keep-alive',
      'Content-Length: 25',
      'Origin: https://www.instagram.com',
      'X-Instagram-AJAX: 1',
      'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
      'Accept: */*',
      'X-Requested-With: XMLHttpRequest',
      'X-CSRFToken: '.$data_rec_token.'',
      'DNT: 1',
      'Referer: https://www.instagram.com/accounts/login/',
      'Accept-Encoding: gzip,deflate',
      'Accept-Language: en-US',
      'Cookie: mid='.$data_rec_mid.'; ig_pr=1; ig_vw=1319; csrftoken='.$data_rec_token.''));
      curl_setopt($ch, CURLOPT_COOKIEFILE, getcwd() . '/instagram_cookie.txt');
      curl_setopt($ch, CURLOPT_COOKIEJAR, getcwd() . '/instagram_cookie.txt');
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 Safari/537.31");
      $data_rec_page = curl_exec($ch) or die(curl_error($ch));
      echo $data_rec_page;
    }
    function instagram_gettoken(){
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_URL, 'https://www.instagram.com/accounts/login/');
      curl_setopt($ch, CURLOPT_HEADER, 0);
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
      curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
      curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
      curl_setopt($ch, CURLOPT_HTTPHEADER, array('application/x-www-form-urlencoded', 'charset=UTF-8'));
      curl_setopt($ch, CURLOPT_COOKIEFILE, getcwd() . '/instagram_cookie.txt');
      curl_setopt($ch, CURLOPT_COOKIEJAR, getcwd() . '/instagram_cookie.txt');
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 Safari/537.31");
      curl_setopt($ch, CURLOPT_REFERER, "https://www.instagram.com/");
      $data_local_lines = file('instagram_cookie.txt');
      foreach($data_local_lines as $data_local_line) {
        if($data_local_line[0] != '#' && substr_count($data_local_line, "\t") == 6) {
          $data_filter_tokens = explode("\t", $data_local_line);
          $data_filter_tokens = array_map('trim', $data_filter_tokens);
          $data_filtered_data[] = $data_filter_tokens[6]; 
        }
      }
      return $data_filtered_data;
    }
    instagram_login("jackzett10","password");
    ?>
    

    在将2D数组传递给函数时也可以使用它:

    {"status":"ok","authenticated":false,"user":"jackzett10"}
    

答案 2 :(得分:2)

这是关于这个主题的一些个人研究。 我在四个不同的环境中运行您的测试代码,两个64位和两个32位 我使用了三种不同的编译器:llvm,gcc和mipsPro cc。
以下是注释结果比较

// 64-bit environment - all compilers
sizeof(int) :     4 -> Fact 1       -32 bit int -> 4 bytes   
sizeof(int*) :    8 -> Fact 2       -this and other pointers in a 64-bit system are 8-bytes long
sizeof(b) :      20 -> Case 1       -array of 5 32 bit ints -> 20 bytes
sizeof((int*)b) : 8 -> Case 2
sizeof(&b[0]) :   8 -> Case 3
sizeof(a) :       8 -> Case 4
sizeof(a[0]) :    8 -> Case 5       -array of two 4 byte ints
sizeof(a[1]) :    8 -> Case 6       -array of two 4 byte ints

// 32-bit environments - all compilers
sizeof(int) :     4 -> Fact 1       -32 bit int -> 4 bytes 
sizeof(int*) :    4 -> Fact 2       -this and other pointers in a 32-bit system are 4-bytes long
sizeof(b) :      20 -> Case 1       -array of 5 32 bit ints -> 20 bytes
sizeof((int*)b) : 4 -> Case 2
sizeof(&b[0]) :   4 -> Case 3
sizeof(a) :       4- > Case 4
sizeof(a[0]) :    8 -> Case 5       -array of two 4 byte ints
sizeof(a[1]) :    8 -> Case 6       -array of two 4 byte ints

解释 - 所有结果始终符合以下模式:

  • int的大小曾经依赖于编译器,也许仍然依赖于AFAIK。它在所有测试环境和编译器中都是4字节(事实1)。
  • 所有指针的大小默认为环境,64位或32位(事实2,案例2,3,4)。
  • 两个四字节整数的数组的大小等于2*sizeof(int)(案例5,6)。
  • a[0]可以改写为*a; a[1]也可以写为*(a + 1)。以下SO post详细阐述了它。

    希望这可以为您的主题做出贡献。