C语言中数组指针与常规指针的比较
我是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;执行此操作。您的问题有点不清楚(并且假设没有编译器优化),但如果先声明变量,
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;
}