正如Joel在Stack Overflow播客#34中用C编程语言(又名:K&R)所指出的那样,在C中提到了数组的这种属性:a[5] == 5[a]
乔尔说,这是因为指针运算,但我仍然不明白.为什么a[5] == 5[a]?
当一个指针到特定类型的(比如int,char,float,..)被递增,其值增加该数据类型的大小.如果void指向大小数据的指针x递增,它如何获得指向x前面的字节?编译器如何知道添加x指针的值?
通过一些C面试问题,我找到了一个问题,指出“如何在不使用sizeof运算符的情况下在C中查找数组的大小?”,并提供以下解决方案。它有效,但是我不明白为什么。
#include <stdio.h>
int main() {
int a[] = {100, 200, 300, 400, 500};
int size = 0;
size = *(&a + 1) - a;
printf("%d\n", size);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如预期的那样,它返回5。
编辑:人们指出了这个答案,但是语法确实有所不同,即索引方法
size = (&arr)[1] - arr;
Run Code Online (Sandbox Code Playgroud)
因此,我认为这两个问题都是有效的,并且对该问题的解决方法略有不同。谢谢大家的大力帮助和详尽的解释!
有没有人对指针算术有任何好的文章或解释(博客,例子)?图中的观众是一群学习C和C++的Java程序员.
在Richard Reese所着的"理解和使用C指针"一书中,它在第85页说
Run Code Online (Sandbox Code Playgroud)int vector[5] = {1, 2, 3, 4, 5};生成的代码与生成的代码
vector[i]不同*(vector+i).该表示法vector[i]生成从位置向量开始的机器代码,从该位置移动i位置,并使用其内容.符号*(vector+i)生成的机器代码从位置开始vector,添加i到地址,然后使用该地址的内容.结果相同,生成的机器代码不同.这种差异对大多数程序员来说很少有意义.
你可以在这里看到摘录.这段经文是什么意思?在什么情况下,任何编译器都会为这两个编译器生成不同的 "移动"与基础之间是否存在差异,而"添加"基数是否存在差异?我无法让它在GCC上工作 - 生成不同的机器代码.
这段代码的行为是否定义得很好?
#include <stdio.h>
#include <stdint.h>
int main(void)
{
void *ptr = (char *)0x01;
size_t val;
ptr = (char *)ptr + 1;
val = (size_t)(uintptr_t)ptr;
printf("%zu\n", val);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的意思是,我们可以为指针分配一些固定数字,即使它指向某个随机地址也会增加它吗?(我知道你不能取消引用它)
请考虑以下代码:
int* p1 = new int[100];
int* p2 = new int[100];
const ptrdiff_t ptrDiff = p1 - p2;
int* p1_42 = &(p1[42]);
int* p2_42 = p1_42 + ptrDiff;
Run Code Online (Sandbox Code Playgroud)
现在,标准保证p2_42指向p2[42]哪个?如果没有,在Windows,Linux或webassembly堆上总是如此吗?
对于指针变量p,p <(p + 1)是否为假是否可能?请解释一下你的答案.如果是,在哪种情况下会发生这种情况?
我想知道p + 1是否会溢出并且等于0.
例如,在64位PC上使用GCC-4.8进行C语言程序:
int main(void) {
void *p=(void *)0xFFFFFFFFFFFFFFFF;
printf("p :%p\n", p);
printf("p+1 :%p\n", p+1);
printf("Result :%d\n", p<p+1);
}
Run Code Online (Sandbox Code Playgroud)
它返回:
p : 0xffffffffffffffff
p+1 : (nil)
Result : 0
Run Code Online (Sandbox Code Playgroud)
所以我相信这种情况是可能的.对于无效的指针位置,它可能发生.这是我能想到的唯一解决方案.还有其他人吗?
注意: 不做任何假设.考虑任何可能发生这种情况的编译器/平台/架构/操作系统.
我继续读到,在C中,使用指针算法通常比下标数组访问更快.即使使用现代(据称是优化的)编译器,这是真的吗?
如果是这样,当我开始在Mac上学习C到Objective-C和Cocoa时,情况仍然如此吗?
在C和Objective-C中,哪种是数组访问的首选编码风格?被认为(由各自语言的专业人士)更清晰,更"正确"(缺乏更好的术语)?
对于指针的减法i和j同一数组对象的元素,[expr.add#5]中的注释读取:
[ 注意:如果值i-j不在类型的可表示值范围内
std?::?ptrdiff_t,则行为未定义.- 结束说明 ]
但是给出[support.types.layout#2],其中指出(强调我的):
- 该类型
ptrdiff_t是一个实现定义的有符号整数类型,它可以保存数组对象中两个下标的差异,如[expr.add]中所述.
结果是否可能i-j不在可表示的值的范围内ptrdiff_t?
PS:如果我的问题是由于我对英语的理解不足造成的,我道歉.
编辑:相关:为什么数组的最大大小"太大"?