为什么我们使用C语言中的指针来存储变量的地址?似乎可以简单地将unsigned int声明为存储地址。
我的问题和下面的问题之间的区别是,它们询问使用不同指针类型的原因,而我询问仅在语言中存在指针的原因。
已经很清楚,地址是引用内存位置的数字,因此不清楚为什么仅访问数字是不够的。
相关但不同的问题:
没有指针的语言是完全有可能的。实际上,可以编写一个C程序,在其中将地址存储在常规整数变量中,然后将其转换为指针。调用指针,以及类型的一般概念,语法糖可以稍微扩展它,但是它也不是完全不正确的。
原因是拥有不同的类型非常有价值。这使编译器可以进行类型检查和自动转换。它还允许编译器在您执行可能不是您想要的操作时警告您。例如,看下面的C代码:
int x;
int *p;
// Init x and p somehow
int y = p + x; // Legal, but you probably meant y = *p + x
Run Code Online (Sandbox Code Playgroud)
早于C的早期语言B仅具有一种称为“单词”的类型。它用于整数,指针,浮点数或其他任何东西。由程序来解释位模式。
考虑下面的C代码:
int i=5;
float f=3.5;
float x=f+i;
Run Code Online (Sandbox Code Playgroud)
在最后一个语句中,i将在float执行浮点加法之前将其提升为。没有类型信息,这将是不可能的。现在x将具有该值8.5(忽略舍入错误),但现在考虑使用此伪代码来说明您在使用B之类的语言时可能遇到的问题:
word i, f, x;
i = 5;
f = 3.5;
x = i + f;
Run Code Online (Sandbox Code Playgroud)
您期望变量x包含什么?那个位模式应该代表什么类型?
当涉及到指针时,这是非常有价值的。考虑到您有两个指针,char *cptr和int *iptr。现在让我们看一下一些指针算法。当将整数添加到指针时,我们将相对于类型的大小偏移指针。因此,*(cptr + 1)将返回后一个字节的值cptr,而*(iptr + 1)(通常)将返回后4或8个字节的地址上的值iptr。
这是一个非常接近您的问题的示例。考虑下面的C代码:
float *p = malloc(10 * sizeof (*p));
for(int i=0; i<10; i++)
p[i]= i * 1.2;
for(int i=0; i<10; i++)
printf("%f\n", p[i]);
Run Code Online (Sandbox Code Playgroud)
如果我们没有指针类型,那么我们将不得不编写如下代码:
unsigned p = malloc(10 * sizeof(float));
for(int i=0; i<10; i++)
*(p + i*sizeof(float)) = i * 1.2;
for(int i=0; i<10; i++)
printf("%f\n", (float) *(p + i*sizeof(float)));
Run Code Online (Sandbox Code Playgroud)
如果您确实想要,那么您实际上可以在C中做类似的事情。这是一个可以编译和运行的示例,尽管带有警告并且可能具有未定义的行为,但是它在我的计算机上产生了预期的结果:
unsigned p = malloc(10 * sizeof(float));
for(int i=0; i<10; i++)
*((float*)p + i*sizeof(float)) = i * 1.2;
for(int i=0; i<10; i++)
printf("%f\n", *((float*)p + i*sizeof(float)));
Run Code Online (Sandbox Code Playgroud)