我对C中的指针表示有疑问。如果我正确理解了C11标准的这一段:
C11(N1570),§6.2.5.28,类型,p。 36
类似地,指向兼容类型的限定或非限定版本的指针应具有相同的表示和对齐要求。
我推断出int *
和int const *
类型具有相同的表示形式,但不是类型int **
和int const **
。我对吗 ?
如果是这样,我想知道为什么这两种类型在第二种情况下没有相同的表示?我的意思是,int
和int const
具有相同的表示形式,int *
和int const *
的同义词,那么int **
和int const **
的问题是什么?
答案 0 :(得分:1)
你是正确的,int *
和int const *
需要使用相同的代表,而int **
和int const **
没有这个要求。
不需要相同表示的原因最有可能避免对C编译器施加不必要的限制以用于奇怪的体系结构,同时使C的规范难以理解而不是需要。
请注意,有些实现例如char*
和int*
具有不同的大小。这可能导致基本的假设,即指向不同类型的指针可以有不同的表示形式,然后对指向兼容类型和指向结构/联合的指针的基本规则进行例外处理。
据我所知,除了DS9K的编译器外,没有任何实现可以利用int **
和int const **
的余地。
答案 1 :(得分:1)
正如Bart van Ingen Schenau所说,我认为标准化委员会希望尽可能少地限制指针的表示。从编译器的角度来看,为int *
和int const *
设置一个独特的表示是有用的,因为常量可以放在更大或更小的内存中,因此可以使用更小的指针指向更小的记忆。但是,这意味着%s
的{{1}}格式说明符应该有两个版本,一个用于常量字符串,另一个用于非常量字符串。这会打破很多遗留代码,我的猜测是标准化委员会缺乏将这一点强加于社区的勇气。也许这是理所当然的。由于没有令人信服的理由强制执行printf
和int **
的相同表示,因此他们就这样做了。然而,对这些指针使用不同的表示几乎没有用,除了可能用于某些极端情况应用程序。
他们可能还认为只有 int const **
和char *
应该具有相同的表示形式,只是为了保存char const *
,但也许还有其他一些接口这也要求指向其他基本类型的指针相等。
类似地,在某些系统上需要为全局内存中的某些内容指定不同的指针表示形式,堆栈中的某些内容以及堆中的某些内容。但是,在C中可以使用一个指针,它可以包含这样的指针(你可以想到varargs),因此至少需要一个可以代表所有指针的指针表示。
在C内存空间的Embedded-C扩展中引入了明确允许程序员从不同数据总线获取数据,而不需要可以代表所有数据总线的指针类型。这样的存储空间也可用于为常量,堆等指定专用存储器。从而允许更有效的指针表示。
我的一位同事也提到K& R原型,或更好的原型,仍然允许。在这种情况下,编译器无法检测参数声明和使用之间的表示差异。毫无疑问,这将导致遗留软件中出现许多未检测到的问题。这些问题可以通过要求在参数传递(包括varargs)上使用公共表示来解决,例如在varags中对%s
到float
进行,但这也会影响到预期的效率。不同的代表。