在C语言中,指针指向一个数组

xmjla07d  于 12个月前  发布在  其他
关注(0)|答案(7)|浏览(218)
#include <stdio.h>
int main()
{
 int (*ptr) [5];
 printf ("%lu\n" , sizeof (ptr));
 printf ("%lu\n" , sizeof (*ptr));
}

字符串
我使用的是64位系统。当我在gcc编译器中运行这段代码时,它会生成输出8 and 20。我的问题是要为这个pointer to an array分配多少字节?是8还是20,为什么?

mmvthczy

mmvthczy1#

我使用的是64位系统。当我在gcc编译器中运行这段代码时,它会生成输出8和20。我的问题是要为这个点分配多少字节到一个数组中?是8还是20,为什么?
首先要考虑的是ptrstatic。除了代码生成中明显的一个之外,没有任何分配:在64位机器中,8个字节用于指针。ptr是指针,并指向一个大小为5 int的区域。编译器会告诉你ptrint(*)[5]。它只是一个指向一个4-byte int machine.并不指向任何东西
所以问题的标题不是我们在代码中所拥有的:没有内存分配
在这里的代码是不多看:

#include <stdio.h>
int main()
{
 int (*ptr) [5];
 printf ("%lu\n" , sizeof (ptr));
 printf ("%lu\n" , sizeof (*ptr));
}

字符串
但考虑

#include <stdio.h>
int main(void)
{
    int(*ptr)[5]   = NULL;
    int  x[5]      = {1, 2, 3, 4, 5};
    ptr            = x;

    printf(
        "\n\
    sizeof ptr       %3zd\n\
    sizeof (*ptr)    %3zd\n\
    sizeof (int[5])  %3zd\n\n    ",
        sizeof ptr, sizeof(*ptr), sizeof(int[5]));

    for (size_t i = 0; i < 5; i += 1)
        printf("%4d ", (*ptr)[i]);
    printf("\n    ");

    x[4]      = 42;  // change last in array
    (*ptr)[0] = 17;  // change 1st using 'ptr'

    for (size_t i = 0; i < 5; i += 1)
        printf("%4d ", (*ptr)[i]);
    printf("\n\n");

    char message[] = "Stack Overflow 1234";
    printf("Message: %s\n", message);
    ptr       = message;
    (*ptr)[4] = 0x00636261;  // change end of string
    printf("Message: %s\n", message);

    return 0;
}


示出

sizeof ptr         8
    sizeof (*ptr)     20
    sizeof (int[5])   20

       1    2    3    4    5
      17    2    3    4   42

Message: Stack Overflow 1234
Message: Stack Overflow 1abc


也许事情变得更清晰了:

  • 线ptr = x;使ptr指向数组x
  • ptr = message;使ptr指向char[]数组。(*ptr)[4] = 0x00636261;将字符串的最后4个字节更改为“abc”。

所有这些都是声明ptrint (*ptr)[5]时括号的效果。
本守则所

#include <stdio.h>
int main(void)
{
  int* ptr[5];
  int  x[5]   = {1, 2, 3, 4, 5};
  ptr[0]      = x + 4;
  ptr[1]      = x + 2;
  ptr[2]      = x + 1;
  ptr[3]      = x + 3;
  ptr[4]      = x;

  printf(
      "\n\
  sizeof ptr       %3zd\n\
  sizeof (*ptr)    %3zd\n\
  sizeof (int[5])  %3zd\n\n    ",
      sizeof ptr, sizeof(*ptr), sizeof(int[5]));

  for (size_t i = 0; i < 5; i += 1)
      printf("%4d ", *ptr[i]);
  printf("\n    ");

  return 0;
}


我们没有括号,

sizeof ptr        40
    sizeof (*ptr)      8
    sizeof (int[5])   20

       5    3    2    4    1


我们看到了正常的东西:一个指向int的5个指针的数组,等等。

c3frrgcw

c3frrgcw2#

我的问题是要为这个点分配多少个字节到一个数组?是8个还是20个,为什么?
这取决于你是需要为指针分配内存还是为它所指向的内存分配内存。
你需要知道你正在看的东西的大小:

#include <stdio.h>

int main() {
    int(*ptr)[5];
    
    printf("%zu\n", sizeof ptr);     // size of a pointer - expression sizeof
    printf("%zu\n", sizeof(void*));  // size of a pointer - type sizeof
    printf("%zu\n", sizeof *ptr);    // size of an int[5] - expression sizeof
    printf("%zu\n", sizeof(int[5])); // size of an int[5] - type sizeof
}

字符串
备注:%lu不是正确的转换。请将%zu用于sizeof

uubf1zoe

uubf1zoe3#

你声明ptr是一个指向5个整数的数组的指针。ptr保存的地址是8个整数。
当你用*ptr查找地址(解引用)时,你会得到一个5个整数的数组,它是5*sizeof(int) = 5*4 = 20

注意:ptr中可能有一个地址,但该地址没有分配内存。

为此,您需要调用ptr = malloc(sizeof(*ptr))
如果不这样做,对数组的访问将发生故障。例如*ptr[0]=0;

waxmsbnn

waxmsbnn4#

ptr指定一个对象,它将存储int的5元素数组的 * 地址 *。在您的系统上,这样的指针占用8个字节的存储空间。

  • 表达式 * *ptr可以指定一个int的5元素数组对象;在您的系统上,这样的数组占用20个字节(5个4字节元素)。

假设代码:

int (*ptr)[5] = malloc( sizeof *ptr );

字符串
这给了你类似下面的东西(每个盒子占用4个字节):

+---+        +---+
ptr: |   | -----> |   | (*ptr)[0]  // we don't want to index into ptr,
     + - +        +---+            // we want to index into what ptr
     |   |        |   | (*ptr)[1]  // *points to*, hence the explicit
     +---+        +---+            // dereference on ptr.  
                  |   | (*ptr)[2]  //
                  +---+            // Since a[i] is defined as *(a + i),
                  |   | (*ptr)[3]  // (*ptr)[i] == (*(ptr + 0))[i] ==
                  +---+            // (ptr[0])[i] == ptr[0][i]
                  |   | (*ptr)[4]  //
                  +---+

sizeof  ptr == sizeof (int (*)[5]) ==  8 // assuming 8-byte addresses
sizeof *ptr == sizeof (int [5])    == 20 // assuming 4-byte int


这相当于写

int arr[5];            // sizeof arr == sizeof (int [5])    == 20
int (*ptr)[5] = &arr;  // sizeof ptr == sizeof (int (*)[5]) ==  8


指针的大小并不取决于它所指向的对象的大小。

hivapdat

hivapdat5#

我的问题是要为这个点分配多少个字节到一个数组?是8个还是20个,为什么?
你不为指向数组或其他对象的指针分配内存。你为数组或其他对象分配内存。指针只是用来指向它。它与内存没有任何内在的关联。
要为数组或其他对象分配内存,您可以告诉malloc您需要为该对象分配多少字节。例如,void *p = malloc(12);为C中使用12字节或更少的任何对象分配内存,只要它没有扩展对齐要求。(C中的所有基本对象,标准的整数、指针和浮点类型,以及由它们组成的数组、联合和结构,都有malloc满足的 * 基本 * 对齐要求。
sizeof运算符将帮助您确定需要多少字节。您可以给予sizeof运算符一个类型,例如对于5个int的数组,int [5],它将给予正确的字节数:

void *p = malloc(sizeof (int [5]));

字符串
注意p的类型与分配的内存或放入的内存无关。指针只是一个指针。
然而,你可以声明一个适当类型的指针,并将其与sizeof一起使用。给定int *p;,则如下代码:

p = malloc(sizeof *p);


表示为p指向的任何类型的对象分配足够的内存。注意,必须使用sizeof *p来表示p指向的大小,而不是sizeof p,因为sizeof p是指针p的大小,而不是p指向的类型的大小。
如果p要指向一个对象数组的第一个对象,你可以通过相乘来得到数组的大小:

p = malloc(5 * sizeof *p);


你也可以使用一个指向整个数组的指针,而不是一个元素,像这样:

int (*p)[5] = malloc(sizeof *p);


没有明确乘以元素的数量,因为*p代表整个数组,而不是其中的单个元素。然而,这种形式并不经常使用,因为使用p访问数组的元素会更困难。由于*p是整个数组,而不是第一个元素,你需要使用(*p)[i]来访问元素i。当p只是指向第一个元素的指针时,你可以使用p[i]来访问一个元素。
因此,声明这样一个指针为int *pint (*p)[5]更受欢迎,除非有额外的情况需要引用整个数组。

q1qsirdb

q1qsirdb6#

在你的代码中,int (*ptr)[5];声明了一个指向5个整数的数组的指针。让我们分解一下大小计算:

  1. sizeof(ptr):这给出了指针本身的大小。在64位系统上,指针通常占用8个字节。因此,sizeof(ptr)将是8。
  2. sizeof(*ptr):这给出了ptr指向的对象的大小,它是一个5个整数的数组(int[5])。数组的大小是一个元素的大小乘以元素的数量。在这种情况下,sizeof(int)在大多数系统上通常是4个字节,而你有5个元素。因此,sizeof(*ptr)将是4 * 5 = 20。
    因此,您看到的输出(sizeof(ptr)为8,sizeof(*ptr)为20)是正确的。这意味着指针本身占用8个字节,它指向的数组(5个整数的数组)占用20个字节。
mutmk8jj

mutmk8jj7#

sizeof运算符可以应用于完整的对象类型。
声明了一个指向int[5]类型数组的指针。

int (*ptr) [5];

字符串
printf的调用

printf ("%lu\n" , sizeof (ptr));


返回指针的大小。注意指针总是完整类型。
*ptr具有完整的数组类型int[5]

printf ("%lu\n" , sizeof (*ptr));


生成一个5个元素的数组,元素类型为int
运算符sizeof产生一个类型为size_t的值。所以你应该重写上面对printf的调用,例如:

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


使用转换说明符zu而不是lu,因为类型size_t不一定是类型unsigned long的别名。C标准允许size_t作为类型unsigned long long的别名,尽管在大多数系统中它确实是类型unsigned long的别名
你可以声明一个指向不完整数组类型的指针,

int (*ptr) [];


正如上面指出的,在任何情况下,指针都是一个完整的类型。

printf ("%zu\n" , sizeof (ptr));


现在,由于这种情况下的数组类型是不完整的,因此对于此语句,

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


编译器将发出错误。
如果一个数组不是可变长度数组,那么它的大小在编译时确定。
你可以声明一个指向可变长度数组的指针。

#include <stdio.h>

int main( void )
{
    for ( size_t i = 1, n = 10; i < n; i++ )
    { 
        int (*ptr) [i];
        printf ("%zu\n" , sizeof (ptr));
        printf ("%zu\n" , sizeof (*ptr));
    }
}


在这种情况下,输出指针大小的printf的调用将打印相同的值。指针的值不会改变,尽管指针指向的数组类型在for循环的每次迭代中都会改变,并且如果变量i并在运行时求值,则输出的数组大小将取决于当前值。时间。尝试自己的演示程序。
请记住,数组的大小计算为数组中元素的数量乘以其元素的大小(元素类型的大小)。

相关问题