C语言中数组指针与常规指针的比较

C语言中数组指针与常规指针的比较,c,arrays,pointers,C,Arrays,Pointers,我是C语言的初学者,所以请用我的无知来学习。为什么普通指针 int*ptr=&a在内存中有两个空格(一个用于指针变量,另一个用于指针所指向的值)和一个数组指针inta[]={5}只有一个内存空间(如果我打印出来 printf(“\n%p\n”,a)我得到的地址与打印出来的地址相同:printf(“\n%p\n”,&a) 问题是,指针变量a和指向第一个数组元素的值不应该有一个内存空间吗?它使用常规指针int*ptr=&a;执行此操作。您的问题有点不清楚(并且假设没有编译器优化),但如果先声明变量,

我是C语言的初学者,所以请用我的无知来学习。为什么普通指针

int*ptr=&a
在内存中有两个空格(一个用于指针变量,另一个用于指针所指向的值)和一个数组指针
inta[]={5}只有一个内存空间(如果我打印出来

printf(“\n%p\n”,a)
我得到的地址与打印出来的地址相同:
printf(“\n%p\n”,&a)


问题是,指针变量
a
和指向第一个数组元素的值不应该有一个内存空间吗?它使用常规指针
int*ptr=&a;

执行此操作。您的问题有点不清楚(并且假设没有编译器优化),但如果先声明变量,然后声明指向该变量的指针

int a = 4;
int *p = &a;
然后你有两个不同的变量,有两个内存槽是有意义的。你可能会把p改成指向其他的东西,并且仍然想在以后引用一个

int a = 4;
int b = 5;

int *p = &a; // p points to a

// ...

p = &b; // now p points to b
a = 6; // but you can still use a
数组声明只是在堆栈上分配内存。如果要在堆上对指针执行同样的操作,可以使用malloc或calloc(或c++中的new)

但是当然记得以后释放它(在c++中删除)


这很简单。在第一种情况下

int*ptr=&a;

您已经声明了一个变量
a
,因此存在于内存中。现在您声明了另一个变量
ptr
(为了保存地址,在C语言中,保存另一个变量地址的变量称为指针),这同样需要内存,与
a
所需的方式相同

在第二种情况下

inta[]={5};


您只需声明一个变量(它将保存一组
int
),因此相应地为
a[]

分配内存。在这个表达式中,
int*p=&a;
p
只有一个内存位置,最有可能是CPU的字大小,并且存储地址(内存位置)是另一个变量的

当您执行
*p
时,您正在解引用
p
,这意味着您正在获取p所指向的值。在这种特定情况下,这将是
a
的值
a
在内存中有自己的位置,
p
指向它,而本身不存储
a
的内容。

当你有一个数组时,比如
inta[]={5};
,你有一系列(或一个)内存位置,它们被值填充。这些是实际的位置

C中的数组可以衰减为指针,因此当您像处理数组一样使用
printf
时,无论您使用
a
还是
&a
,都会得到相同的地址。这是由于数组到指针的衰减


a
仍然是相同的位置,并且只是该位置。
&a
实际上返回指向
a
的指针,但该指针位于内存中的其他位置。如果您这样做了
int*b=&a;
,则
b
此处的位置将与
a
不相同,但是,它将指向
a
一种包含内存地址的变量。您可以将各种内存地址分配给ptr。a是一个常数,表示数组第一个元素的固定内存地址。因此,您可以执行以下操作:

ptr = a;
但不是

a = ptr;

指针指向内存中的一个区域。指向
int
的指针指向一个足以容纳
int
类型值的区域

如果您有一个
int
数组,并将指针指向数组的第一个元素

int array[42];
int *p = array;
指针仍然指向一个足够大的空间,可以容纳int

另一方面,如果将不同的指针指向整个数组,则新指针将指向从同一地址开始的更大区域

 int (*q)[42]; // q is a pointer to an array of 42 ints
 q = &array;

p
q
的地址相同,但它们指向不同大小的区域。

这里的主要误解是
&a
没有像预期的那样返回指向指针的指针,这是因为在C语言中,[]和*(此处解释:) 如果您尝试
&a
如果a是指针(例如int*a),那么您将获得一个新的内存位置,但是当您使用静态数组(例如int a[])时,它将返回第一个数组元素的地址。我还将尝试通过下一个代码块来澄清这一点

#include <stdio.h>

int main(int argc, char *argv[])
{
    // for cycles
    int k; 

    printf("That is a pointer case:\n");
    // Allocate memory for 4 bytes (one int is four bytes on x86 platform, 
    // can be differ for microcontroller e.g.)
    int c = 0xDEADBEEF;
    unsigned char *b = (unsigned char*) &c;
    printf("Value c: %p\n", c);
    printf("Pointer to c: %p\n", &c);
    printf("Pointer b (eq. to c): %p\n", b);
    // Reverse order (little-endian in case of x86)
    for (k = 0; k < 4; k++)
        printf("b[%d] = 0x%02X\n", k, b[k]);

    // MAIN DIFFERENCE HERE: (see below)    
    unsigned char **p_b = &b;
    // And now if we use & one more we obtain pointer to the pointer
    // 0xDEADBEEF <-- b <-- &p_b
    // This pointer different then b itself
    printf("Pointer to the pointer b: %p\n", p_b);

    printf("\nOther case, now we use array that defined by []:\n");
    int a[] = {5,1};
    int *ptr = &a;
    // 'a' is array but physically it also pointer to location
    // logically it's treat differ other then real pointer
    printf("'a' is array: %x\n", a);
    // MAIN DIFFERENCE HERE: we obtain not a pointer to pointer
    printf("Pointer to 'a' result also 'a'%x\n", &a);
    printf("Same as 'a': %x\n", ptr);
    printf("Access to memory that 'a' pointes to: \n%x\n", *a);

    return 0;
}
#包括
int main(int argc,char*argv[])
{
//循环
int k;
printf(“这是一个指针大小写:\n”);
//为4个字节分配内存(在x86平台上,一个int等于4个字节,
//微控制器可能不同,例如)
int c=0x0;
无符号字符*b=(无符号字符*)&c;
printf(“值c:%p\n”,c);
printf(“指向c的指针:%p\n”,&c);
printf(“指针b(指向c的等式):%p\n”,b);
//相反顺序(x86情况下为小端)
对于(k=0;k<4;k++)
printf(“b[%d]=0x%02X\n”,k,b[k]);
//这里的主要区别:(见下文)
无符号字符**p_b=&b;
//现在如果我们再使用一个,我们就得到了指向指针的指针

//第一个示例只有一个“空格”——指针本身的空格。
a
在别处定义。但重要的是要记住,C指针不包含它所寻址的数组大小的指示,即使它甚至寻址数组。(你不能真正开始理解C指针,除非你把它们是“逻辑的”这一期望放在一边。)你必须记住,如果
a
被声明为数组,那么
a
&a
@HotLicks-Licks在本质上是相同的。我相信如果它们是由一个人设计的,另一个人也能理解它们。你真的没有给我一个有用的答案,但谢谢你。@polymorph这只是规则。如果
arr
是一个数组,键入
arr
将为您提供指向第一个el的指针
 int (*q)[42]; // q is a pointer to an array of 42 ints
 q = &array;
#include <stdio.h>

int main(int argc, char *argv[])
{
    // for cycles
    int k; 

    printf("That is a pointer case:\n");
    // Allocate memory for 4 bytes (one int is four bytes on x86 platform, 
    // can be differ for microcontroller e.g.)
    int c = 0xDEADBEEF;
    unsigned char *b = (unsigned char*) &c;
    printf("Value c: %p\n", c);
    printf("Pointer to c: %p\n", &c);
    printf("Pointer b (eq. to c): %p\n", b);
    // Reverse order (little-endian in case of x86)
    for (k = 0; k < 4; k++)
        printf("b[%d] = 0x%02X\n", k, b[k]);

    // MAIN DIFFERENCE HERE: (see below)    
    unsigned char **p_b = &b;
    // And now if we use & one more we obtain pointer to the pointer
    // 0xDEADBEEF <-- b <-- &p_b
    // This pointer different then b itself
    printf("Pointer to the pointer b: %p\n", p_b);

    printf("\nOther case, now we use array that defined by []:\n");
    int a[] = {5,1};
    int *ptr = &a;
    // 'a' is array but physically it also pointer to location
    // logically it's treat differ other then real pointer
    printf("'a' is array: %x\n", a);
    // MAIN DIFFERENCE HERE: we obtain not a pointer to pointer
    printf("Pointer to 'a' result also 'a'%x\n", &a);
    printf("Same as 'a': %x\n", ptr);
    printf("Access to memory that 'a' pointes to: \n%x\n", *a);

    return 0;
}