我是C的初学者,请与我的无知一起工作。为什么是普通指针
int* ptr = &a;
在内存中有两个空格(一个用于指针变量,一个用于指向的值),数组指针int a[] = {5};
只有一个内存空间(如果我打印出来
printf("\n%p\n", a)
我得到的地址与打印出来的地址相同:printf("\n%p\n", &a)
。
问题是,是否应该有一个指针变量a
的内存空间,以及一个指向第一个数组元素的值的内存空间?它使用常规指针int* ptr = &a;
答案 0 :(得分:2)
你的问题有点不清楚(假设没有编译器优化),但如果你先声明一个变量然后指向该变量的指针,
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)这样的东西
int *p = (int*)malloc(1 * sizeof(int));
*p = 4;
但当然记得稍后将其释放(在c ++中删除)
free(p);
p = 0;
答案 1 :(得分:1)
这里的主要误解是&a
没有返回指针指向预期的指针,因为在C语言中,[]和*之间存在一些差异(这里的解释:Difference between [] and *)
如果你尝试&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;
}
答案 2 :(得分:0)
这很简单。在第一种情况下,
int* ptr = &a;
您已经声明了一个变量a
,因此存在于内存中。现在你声明另一个变量ptr
(用于保存地址,在C变量中保存另一个变量的地址称为指针),这再次需要内存的方式与{{1}相同} required。
在第二种情况下,
a
您只需声明一个变量(将包含int a[] = {5};
的集合),因此会为ints
相应地分配内存。
答案 3 :(得分:0)
在这个表达式中,int* p = &a;
p
只有一个内存位置,最可能是CPU的WORD大小,用于存储另一个的地址(内存位置)变量强>
执行*p
时,您解除引用 p
,这意味着您将获得 p指向的值。在这种特殊情况下,这将是a
的值。 a
在内存中有自己的位置,p
只有指向它,但本身并不存储a
的内容。
如果你有一个数组,比如int a[] = {5};
,那么你有一系列(或一个)内存位置,并且它们充满了值。这些是实际的位置。
C中的数组可以衰减指针,所以当你printf
就像使用数组一样,无论你做a
还是{&a
,都会得到相同的地址{1}}。这是因为数组到指针衰减。
a
仍然是同一个位置,而且只是该位置。 &a
实际上返回一个指向a
的指针,但该指针位于内存中的其他位置。如果您int* b = &a;
b
,那么a
与a
的位置不同,但指向 {{1}}。
答案 4 :(得分:0)
ptr是一个包含内存地址的变量。您可以为ptr分配各种内存地址。 a是表示数组第一个元素的固定内存地址的常量。你可以这样做:
ptr = a;
但不是
a = ptr;
答案 5 :(得分:-1)
指针指向内存中的某个区域。指向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
的地址相同,但它们指向不同大小的区域。