Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.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_Pointers - Fatal编程技术网

C 访问分配内存中的变量

C 访问分配内存中的变量,c,pointers,C,Pointers,假设我想为3个整数分配内存: int *pn = malloc(3 * sizeof(*pn)); 现在,要为它们指定值,我需要: pn[0] = 5550; pn[1] = 11; pn[2] = 70000; 要访问第二个值,我需要: pn[1] 但是[n]运算符只是*(a+n)的快捷方式。这意味着我访问索引后的第一个字节。但是int是4字节长的,我不应该这样做吗 *(a+sizeof(*a)*n) 相反?它是如何工作的?这是一个好问题,但C会自动将偏移量乘以指向类型的大小。换句话说

假设我想为3个整数分配内存:

int *pn = malloc(3 * sizeof(*pn));
现在,要为它们指定值,我需要:

pn[0] = 5550;
pn[1] = 11;
pn[2] = 70000;
要访问第二个值,我需要:

pn[1]
但是[n]运算符只是*(a+n)的快捷方式。这意味着我访问索引后的第一个字节。但是int是4字节长的,我不应该这样做吗

*(a+sizeof(*a)*n)

相反?它是如何工作的?

这是一个好问题,但C会自动将偏移量乘以指向类型的大小。换句话说,当您访问

p[n]
对于声明为

T *p;

您将隐式地访问地址
p+(sizeof(T)*n)

否,编译器会处理这个问题。指针算法中有一些特殊的规则,这就是其中之一


如果您真的只想将其递增一个字节,则必须将指针转换为指向一个一字节长类型的指针(例如
char
)。

例如,我们可以使用C99标准来了解发生了什么。根据C99标准:

6.5.2.1阵列订阅
约束条件
- 1 其中一个表达式的类型应为“指向对象类型的指针”,另一个表达式的类型应为 具有整数类型,且结果的类型为“类型”。
语义
-2后缀表达式后跟方括号中的表达式为下标表达式 指定数组对象的元素。下标运算符的定义[] 是不是E1[E2]相同(*((E1)+(E2))。因为转换规则 如果E1是数组对象(相当于指向 数组对象的初始元素)且E2为整数,E1[E2]指定E2 th E1的元素(从零开始计数)

从6.5.5.8开始,关于
+
运算符的转换规则:

在指针中添加或减去整数类型的表达式时 结果具有指针操作数的类型。如果指针操作数指向 数组对象,并且数组足够大,结果指向从 原始元素,使得结果和原始元素的下标不同 数组元素等于整数表达式。换句话说,如果表达式P指向 数组对象的第i个元素,表达式(P)+N(相当于N+(P))和 (P) -N(其中N的值为N)分别指向i+N-th和i−第n元素 数组对象,前提是它们存在。此外,如果表达式P指向最后一个 数组对象的元素,表达式(P)+1指向 数组对象,如果表达式Q指向数组对象最后一个元素的上方, 表达式(Q)-1指向数组对象的最后一个元素。如果两个指针 操作数和结果指向同一数组对象的元素,或超过最后一个的元素 数组对象的元素,求值时不应产生溢出;否则 行为是未定义的。如果结果指向数组对象的最后一个元素后一个元素,则 不得用作计算的一元*运算符的操作数

因此,所有这些注释都是关于您的案例的,它完全按照您所写的那样工作,您不需要特殊的构造、解引用或其他任何东西(指针算术可以为您这样做):

或者,就字节指针而言(为了简化描述),此操作类似于:

pn[1] => *(((char*)pn) + (1*sizeof(*pn)))

此外,您可以使用
1[pn]
访问此元素,结果将是相同的。

您不应该这样做。将int添加到指针时发生的规则并不明显。所以最好不要使用你的直觉,而是阅读语言标准,了解在这种情况下会发生什么。例如,阅读有关指针算术(C)或(C++)的更多信息


简而言之,非空指针是以类型长度为单位“测量”的。

每个C编译器都必须这样做吗(是严格的、标准化的吗)?是的。至少是C语言定义的字节。那么*(n+1)呢?它是访问第二个字节还是与n[1]的工作原理相同?它与
n[1]
的工作原理相同。正如您在文章中所指出的,
[]
在这种情况下只是一种快捷方式。绝对没有任何东西表明
*(a+n)
是以字节为单位工作的;除非
a
当然是字节指针。所有指针运算都是指针的类型。我会仔细考虑这个页面,它会说C的内容,但是大部分代码是C++。
pn[1] => *(((char*)pn) + (1*sizeof(*pn)))