一个 int 指针是一个 int 数组吗?

6

我一直在跟随一些声明整型指针的示例

int *myInt;

将指针转换为数组。
myInt = (int*)malloc(1024);

这是正确的。
myInt[0] = 5; 
cout << myInt[0]; // prints 5
myInt[1] = 7;
cout << myInt[1]; // prints 7

我曾以为int指针只是指向int,没有其他用途。我知道指向字符串的指针只是指向字符串的第一个字符,但是在这里,似乎指向int数组的指针也是同样的情况。但如果我们需要的是int数组,为什么不直接创建一个int数组而不是一个int指针呢?
顺便说一下,我对C语言中的这个问题很感兴趣,而不是C++。虽然这段代码在C++文件中,但相关的代码是用C编写的。

3
好的,以下是翻译的结果:标题: C 数组指针和数组名的等价性当您使用C语言中的数组时,指向该数组的指针和该数组的名称具有相同的值。这意味着您可以使用指针或数组名称来访问数组元素。例如,假设您有一个名为array的整数数组,并且您声明了一个指向该数组的指针p,则以下表达式都具有相同的值:array[i] *(p+i) *(i+p) p[i]这是因为在C语言中,使用数组名称作为指针会自动转换为指向该数组的第一个元素的指针。因此,以上所有表达式都是对同一内存位置中的数据进行操作。需要注意的是,尽管指针和数组名称具有等效的值,但它们并不完全相同。特别是,您不能将另一个数组的名称分配给指针变量。 - JAB
4
在C语言中,你不需要显式地使用void *指针。请注意不要改变原意。 - user405725
2
一个int指针不是int的数组。指针指向内存中的一个地址。地址是int类型的。所以,如果我没弄错的话,当你使用malloc分配数组时,你将正在分配的数组的地址存储在*myInt中。 - jonhopkins
通常情况下,您还会使用malloc(n * sizeof(int)),否则您获得的整数数量可能取决于平台,因为您保留了1024个字节。这通常不是某人想要的。 - hetepeperfan
@jonhopkins - 不,地址不是 int 类型,地址被存储在 myInt 中,而不是 *myInt - detly
给楼主 - 你可能会发现《C语言书籍》(http://publications.gbdirect.co.uk/c_book/chapter5/)是一个有用的参考资料。 - detly
5个回答

12
一个 int 指针是 int 数组吗?
不是的。
我认为 int 指针只是指向 int 的指针,没有别的。
没错。指针就是指针,数组就是数组。让你感到困惑的是指针可以指向数组的第一个元素,而数组可以衰变成指向它们第一个元素的指针。更令人困惑的是:指针具有与数组索引使用的解引用和指针算术相同的语法。也就是说,
ptr[i]

等同于

*(ptr + i)

如果ptr是指针。当然,同样地,arr[i]也是arr数组的第i个元素。指针和数组的共性在于它们都用于间接访问(可能是块)内存。

这种强关系的结果是,在某些情况下(以及在某些限制条件下),数组和指针可以被用作可以互换的。这仍然并不意味着它们是相同的,但它们表现出足够共同的特性,以便它们的使用通常看起来是“相同的”。


3

访问指针所指向的项目有一种替代语法 - 方括号。这种语法使您可以通过指针访问数据,就好像指针是一个数组(当然,指针不是数组)。表达式a[i]只是写作*(a+i)*的另一种形式。

当您分配动态存储并将其分配给myInt时,可以像使用可在运行时更改大小的动态数组一样使用指针:

myInt = malloc(1024*sizeof(int)); // You do not need a cast in C, only in C++
for (int i = 0 ; i != 1024 ; i++) {
    myInt[i] = i; // Use square bracket syntax
}
for (int i = 0 ; i != 1024 ; i++) {
    printf("%d ", *(myInt+i)); // Use the equivalent pointer syntax
}


* 顺便提一下,+的交换性使您可以编写4[array]而不是array[4];请不要这样做!


1
@AK4749 公平地说,我之前也从未想过这个问题,直到我开始为一家明确禁止在其编码手册中使用此类表达式的公司工作(该手册表示“如果我们发现你写了4 [array],你就被解雇了”)。 - Sergey Kalinichenko

1
他们并不相同。以下是它们的显著区别。
int  array[10];
int  *pointer;

printf ("Size of array = %d\nSize of pointer = %d\n",
    sizeof (array), sizeof (pointer));

结果是,
Size of array = 40
Size of pointer = 4

如果您执行 "array + 1",则结果地址将是 array[0] 的地址 + 40。如果您执行 "pointer + 1",则结果地址将是 pointer[0] 的地址 + 4。
数组声明会导致编译时内存分配。指针声明不会导致编译时内存分配,需要使用 calloc() 或 malloc() 进行动态分配。
当您执行以下赋值时,实际上是将整数数组隐式类型转换为整数指针。
pointer = array; 

1

从技术上讲,是和不是。一个int指针确实指向int。但是int数组在内存中是连续的,所以下一个int可以使用*(myInt+1)来引用。数组符号myInt[1]等价于它,因为它使用myInt指针,将其加上1个单位(int的大小),并引用该新地址。

所以一般情况下,这是正确的:

myInt[i] == *(myint + i)

所以你可以使用int指针来访问数组。只需小心注意'\0'字符并停止即可。

一个数组的结尾是否保证被标记为 '\0'?我认为不是。 - im so confused
int 数组中查找 '\0' 字符并不是一个明智的选择。在大多数 32 位系统上,你所查看的那个 int 中将会有四个单独的字符的等效形式。 - Crowman

1
一个int指针不是一个int数组。但你更大的问题似乎是为什么需要数组和指针两者。
数组表示数据在内存中的实际存储。一旦分配了存储空间,使用数组符号或指针符号引用存储的数据并没有太大区别。
然而,这个存储空间也可以在不使用数组符号的情况下分配,这意味着数组不一定是必需的。数组的主要好处是方便地分配小块内存,例如int x[20]和略微更方便的符号array[i]而不是*(array+i)。值得庆幸的是,无论array来自数组声明还是只是一个指针,都可以使用这种更方便的符号。(从本质上讲,一旦数组被分配,它的变量名从那时起与被分配指向数组第一个值的指针没有任何区别。)
请注意,如果您尝试直接分配太大的内存块到数组中,编译器会发出警告。 数组:
  • 代表实际分配的内存
  • 数组的变量名与指向数组开始处的指针相同(如果存在第二个元素,则变量名+1与指向第二个元素开始处的指针相同,以此类推)
  • 可以使用数组表示法(如array[i])访问数组中的值

指针:

  • 指针是存储内存中某个位置的地方
  • 可以引用分配在数组中的内存
  • 也可以引用由malloc等函数分配的内存
  • 通过对指针进行解引用,即*pointer,可以访问指针所指向的内存中存储的值。
  • 由于数组的名称也是指针,因此可以通过*array访问数组中的第一个元素的值,通过*(array+1)访问第二个元素的值,以此类推。
  • 整数可以加或减到指针上,以创建一个新的指针,该指针指向程序已分配的同一块内存中的其他值。例如,array+5指向存储array[5]值的内存中的位置。
  • 指针可以增加或减少,以指向同一块内存中的其他值。

在许多情况下,一种符号比另一种更方便,因此拥有两种符号非常有益,并且它们之间如此容易互换。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接