当仅数字的概念就足够时,是什么激发了C语言中“指针”的概念呢?

时间:2019-04-04 12:57:36

标签: c pointers int

为什么我们使用C语言中的指针来存储变量的地址?似乎可以简单地将unsigned int声明为存储地址。

我的问题和下面的问题之间的区别是,他们询问具有不同指针类型的原因,而我询问语言中仅存在指针的原因。

已经很清楚地址是引用内存位置的数字,因此不清楚为什么仅访问数字是不够的。

相关但不同的问题:

4 个答案:

答案 0 :(得分:6)

TL; DR

完全有可能没有指针的语言。实际上,可以编写一个C程序,在其中将地址存储在常规整数变量中,然后将其转换为指针。调用指针,以及类型的一般概念,语法糖可以稍微扩展它,但它也不是完全不正确的。

长话

原因是拥有不同的类型非常有价值。这使编译器可以进行类型检查和自动转换。它还允许编译器在您执行可能不是您想要的操作时警告您。例如,看下面的C代码:

int x;
int *p;
// Init x and p somehow
int y = p + x; // Legal, but you probably meant y = *p + x

早于C的早期语言B只有一种叫做“单词”的类型。它用于整数,指针,浮点数或其他任何东西。由程序来解释位模式。

考虑以下C代码:

int i=5;
float f=3.5;
float x=f+i;

在最后一条语句中,将在执行浮点加法之前将i提升为float。没有类型信息,这将是不可能的。现在x的值为8.5(舍入误差被忽略),但是现在考虑这个伪代码,它说明了使用B等语言时可能遇到的问题:

word i, f, x;
i = 5;
f = 3.5;
x = i + f;

您期望变量x包含什么?那个位模式应该代表什么类型?

当涉及到指针时,这是非常有价值的。考虑到您有两个指针char *cptrint *iptr。现在让我们看一下一些指针算法。当将整数添加到指针时,我们将相对于类型的大小偏移指针 。因此,*(cptr + 1)将返回cptr之后一个字节的值,而*(iptr + 1)将(通常)返回iptr之后4或8个字节的地址上的值。

这是一个非常接近您的问题的示例。考虑下面的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]);

如果没有指针类型,那么我们将不得不编写如下代码:

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)));

如果您确实想要,您实际上可以在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)));

答案 1 :(得分:1)

因为它通过提供有关该变量的用途,它可以具有的值以及可以对其执行哪些操作的提示,对程序员有所帮助。

计算机不在乎。

答案 2 :(得分:1)

如其他答案所述,为指针使用单独的类型可以澄清意图,并允许编译器执行与使用指针有关的检查。

即使没有这种情况,对指针使用整数类型也是有意义的。假设,将内存引用为字节的平面数组。但是,并非所有系统都必须用单个整数表示内存地址。

一个值得注意的例子是实模式下的x86处理器。这些处理器之一启动时,它将以实模式启动。此模式一直返回到原始的16位8086处理器。在此模式下,存储器以16位段和16位偏移量寻址,这两个地址共同构成20位地址。通过将段左移4位并加上偏移量来组合它们。例如:

segment: 0x1111
offset:   0x2222
address: 0x13332

在这样的布局中,也可能有两个具有不同数值的指针,它们引用相同的地址:

segment: 0x1110
offset:   0x2232
address: 0x13332

因此,一个值为0x1111:0x2222的指针和另一个值为0x1110:0x2232的指针指向同一地址。

此寻址模型还具有近指针和远指针的概念,其中近指针仅包含偏移量(并假定CS寄存器中的当前段),而远指针同时包含段和偏移量。

因此您不能仅用整数来表示指针,因为对于某些体系结构而言,这还不够。

答案 3 :(得分:0)

因为用不同的方式表示它们很有用。您还希望通过写出字符的十六进制值来指定字符串吗?