Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ “是什么意思?”;内存地址的差异;_C++_C - Fatal编程技术网

C++ “是什么意思?”;内存地址的差异;

C++ “是什么意思?”;内存地址的差异;,c++,c,C++,C,考虑 #include <cstdio> int main() { char a[10]; char *begin = &a[0]; char *end = &a[9]; int i = end - begin; printf("%i\n", i); getchar(); } #包括 int main(){ chara[10]; char*begin=&a[0]; char*end=&a[9]; int i=结束-开

考虑

#include <cstdio>

int main() {
    char a[10];
    char *begin = &a[0];
    char *end = &a[9];
    int i = end - begin;
    printf("%i\n", i);
    getchar();
}
#包括
int main(){
chara[10];
char*begin=&a[0];
char*end=&a[9];
int i=结束-开始;
printf(“%i\n”,i);
getchar();
}

#包括
int main(){
INTA[10];
int*begin=&a[0];
int*end=&a[9];
int i=结束-开始;
printf(“%i\n”,i);
getchar();
}

#包括
int main(){
双a[10];
双*开始=&a[0];
双*端=&a[9];
int i=结束-开始;
printf(“%i\n”,i);
getchar();
}
以上三个示例也打印9


请问,我该如何解释9的意思。它是什么意思?

9表示&a[9]和&a[0]之间类型为“T”的元素数(其中T是char,int,按该顺序分别为double)

它们之间的实际字节数是
(&a[9]-&a[0])*sizeof(T)
。注意sizeof(char)的定义是1。进一步注意,字节不是强制要求为8位的。相反,它是一些8位内存位置,需要用来保存实现的基本字符集中的所有字符


编辑:正如@pmg所指出的,字节被定义为一个足够宽的内存位置,可以容纳实现的基本字符集中的所有字符。

指向某些类型的指针之间的差异是它们之间的实例数(也就是说,它相当于数组索引之间的差异)。或者换句话说,它相当于(不确定是否为正确的整数类型)

6.5.6.9减去两个指针时,两个指针都应指向 同一数组对象的元素,或 超过数组最后一个元素一个 对象结果就是不同 两个数组的下标的 元素


编译器将根据指针类型自动计算指针算术,这就是为什么不能使用
void*
(无类型信息)或混合指针类型(不明确类型)执行操作的原因

在MSVC2008中(我相信在大多数其他编译器中),语法被解释为计算两个指针之间的元素差异量

int i = end - begin;
00411479  mov         eax,dword ptr [end] 
0041147C  sub         eax,dword ptr [begin] 
0041147F  sar         eax,3 
00411482  mov         dword ptr [i],eax 
由于减法之后是右移,因此结果将向下舍入,因此保证N元素可以装入两个指针之间的内存空间(并且可能存在未使用的间隙)。下面的代码也证明了这一点,结果也是9

int main()
{
    double a[10];
    double *begin = &a[0];
    char *endc = (char*)&a[9];
    endc += 7;
    double *end = (double*)endc;
    int i = end - begin;
    printf("%i\n", i);
    getchar();

    return 0;
}

想想减法的定义:如果

r = b - a
意思是

b = a + r
指针也是如此:

ptrdiff_t res = end - begin;
因此

现在,了解了常规指针算术规则,您可以很容易地推断出
res
是分隔
begin
end
的元素数(属于
begin
end
所指向的类型)



请注意,我没有使用
int
作为
res
的类型,而是
ptrdiff\u t
:这是非常有意的,因为
ptrdiff\u t
被定义为“两个指针之间的减法操作返回的类型”(),因此它是保存此类结果的完美类型。

这意味着&a[0]+9与&a[9]相同不管是什么类型。这就像是在冒泡意大利马特奥在他的回答中给出的重要信息:永远不要使用
int
来表示指针的差异,
ptrdiff\u t
才是正确的
typedef
。@Jen Gustedt:如果你确定差异将适合
int
(比如在本例中),那么使用
int
就可以了。@caf:当然,你是对的,如果你知道你在做什么,很多事情在C中都会很好;-)但是使用
int
而不是
ptrdiff\t
只不过是一个坏习惯,特别是初学者(正如我所说的,无意冒犯)应该从好习惯开始,嗯,一个字节可以是9位,也可以是36位。。。它不需要是8位的倍数。所有实现都有一个预定义的宏常量,该常量为该实现指定字节:CHAR\u BIT中有多少位。@pmg:Yes。谢谢你指出这一点。已经更正了post,标准的引号非常清楚-这是数组下标的差异。
r = b - a
b = a + r
ptrdiff_t res = end - begin;
end == begin + res