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

在C语言中,当数字的概念已经足够时,是什么激发了“指针”的概念?,c,pointers,int,C,Pointers,Int,为什么我们在C语言中使用指针来存储变量的地址?似乎可以简单地声明一个无符号int来存储地址 我的问题和下面的问题的区别在于,他们问的是指针类型不同的原因,而我问的是,语言中存在指针的概念的原因 已经很清楚,地址是引用内存位置的数字,所以不清楚为什么只访问数字是不够的 相关但不同的问题: TL;博士 完全可以有一种没有指针的语言。实际上,可以编写一个C程序,将地址存储在正则整数变量中,然后将它们转换为指针。调用指针,以及类型的一般概念,语法上的甜点是对它进行一些扩展,但也不是完全不正确的 长话短说

为什么我们在C语言中使用指针来存储变量的地址?似乎可以简单地声明一个无符号int来存储地址

我的问题和下面的问题的区别在于,他们问的是指针类型不同的原因,而我问的是,语言中存在指针的概念的原因

已经很清楚,地址是引用内存位置的数字,所以不清楚为什么只访问数字是不够的

相关但不同的问题:

TL;博士 完全可以有一种没有指针的语言。实际上,可以编写一个C程序,将地址存储在正则整数变量中,然后将它们转换为指针。调用指针,以及类型的一般概念,语法上的甜点是对它进行一些扩展,但也不是完全不正确的

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

int x;
int *p;
// Init x and p somehow
int y = p + x; // Legal, but you probably meant y = *p + x
int i=5;
float f=3.5;
float x=f+i;
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]);
一种早于C的早期语言B只有一种称为word的类型。它被用于整数、指针、浮点或其他任何东西。由程序来解释位模式

考虑以下C代码:

int x;
int *p;
// Init x and p somehow
int y = p + x; // Legal, but you probably meant y = *p + x
int i=5;
float f=3.5;
float x=f+i;
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]);
在最后一条语句中,在执行浮点加法之前,我将被提升为浮点。如果没有类型信息,这是不可能的。现在,X将忽略8.5个舍入误差,但是现在考虑这个伪代码,它说明了在B: < /P>这样的语言中会遇到的问题。
word i, f, x;
i = 5;
f = 3.5;
x = i + f;
您希望变量x包含什么?那个位模式应该代表什么类型

说到指针,这是非常有价值的。假设您有两个指针,char *CPTR和int *IPTR。现在让我们看看一些指针算法。当向指针添加整数时,我们将根据类型的大小偏移指针。因此,*cptr+1将返回cptr后一个字节的值,而*iptr+1通常将返回iptr后4或8个字节的地址上的值

这是一个非常接近你的问题的例子。考虑这个C代码:

int x;
int *p;
// Init x and p somehow
int y = p + x; // Legal, but you probably meant y = *p + x
int i=5;
float f=3.5;
float x=f+i;
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)));
因为它可以帮助你,程序员,提供一个关于变量的用途,它可以有什么值,以及你可以用它做什么操作的提示


计算机不在乎。

正如其他答案所提到的,为指针指定一个单独的类型可以澄清意图,并允许编译器执行与使用指针相关的检查

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

一个值得注意的例子是实模式下的x86处理器。当其中一个处理器启动时,它以实模式启动。这种模式可以追溯到最初的16位8086处理器。这种模式下的内存由一个16位段和一个16位偏移量寻址,它们共同构成一个20位地址。它们通过将段向左移动4位并添加偏移量来组合。例如:

段:0x1111 偏移量:0x2222 地址:0x13332 在这样的布局中,也可能有两个指针,它们具有不同的数值,引用相同的地址:

段:0x1110 偏移量:0x2232 地址:0x13332 因此,一个值为0x1111:0x2222的指针和另一个值为0x1110:0x2232的指针指向同一地址

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


因此,不能用一个整数来表示指针,因为这对于某些体系结构来说是不够的。

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

C有五种无符号in类型,它们的大小可以不同,也可以相同。我们应该使用哪种无符号整数类型,考虑到没有一种类型可能大到足以容纳内存地址?此外,一旦在无符号整数变量中有了地址,访问该地址内存的语义是什么?你怎么能分辨出一个整数和另一个整数的区别呢
包含一个地址,而一个整数包含另一个不是地址的整数值?重复项是相关的,但在我看来并不是这个问题的重复项。因为指针算法依赖于类型-如果p指向t类型的对象,那么p+1指向该类型的下一个对象,不一定是下一个字节。指针是具有附加类型语义的地址的抽象,这就是它们的用处所在。此外,指针值不必是标量-它们可以是像页码和偏移量对这样的聚合。这两个重复的问题确实为为什么需要指针类型提供了一些很好的理由。请注意,重复只是指向回答问题的有用答案,问题本身是否相同与否无关。我不知道关键字这个词。我真的找到了你的答案helpful@MadhusudanBabar:如果你感兴趣,这里有一个关于B编程语言的教程。你可以看到它是如何影响C的发展的。@MadhusudanBabar单词不是B中的关键字。相反,你会写auto。但考虑到上下文,我认为写单词会更清楚。毕竟,我并没有试图编写可编译的B代码,只是展示了类型化语言的优点。这里有一个很好的答案,请注意,所有语言功能的答案都是相似的,即使是语言存在的原因。您如何/为什么设计语言或语言概念?通过思考原则上不必要、技术上不必要、但尽可能有助于人类提高生产力和效率的概念抽象。这就是为什么语言设计需要的不仅仅是技术知识,它在某种程度上是主观的。例如,有些人喜欢这种语言,我发现它是一场噩梦:最后一个极端的例子,如果我正确地回忆起一个逻辑门,它可以是图灵完全的。例如,想象一个这样的逻辑门。它几乎什么都不做,对吗?然而,您可以编写任何可能的应用程序,只需使用大量这个简单的低级组件。问题是这样做后你会神志清醒吗-