我有以下代码。也许我没有理解指针算法以及我应该有但是为什么int_pointer增加4而不是1?使用char_pointer,为什么它不会增加4而不是1?
#include <stdio.h>
int main() {
int i;
char char_array[5] = {'a', 'b', 'c', 'd', 'e'};
int int_array[5] = {1, 2, 3, 4, 5};
char *char_pointer;
int *int_pointer;
char_pointer = int_array; // The char_pointer and int_pointer now
int_pointer = char_array; // point to incompatible data types.
for(i=0; i < 5; i++) { // Iterate through the int array with the int_pointer.
printf("[integer pointer] points to %p, which contains the char '%c'\n",
int_pointer, *int_pointer);
int_pointer = int_pointer + 1;
}
for(i=0; i < 5; i++) { // Iterate through the char array with the char_pointer.
printf("[char pointer] points to %p, which contains the integer %d\n",
char_pointer, *char_pointer);
char_pointer = char_pointer + 1;
}
}
输出:
[integer pointer] points to 0xbffff810, which contains the char 'a'
[integer pointer] points to 0xbffff814, which contains the char 'e'
[integer pointer] points to 0xbffff818, which contains the char ' '
[integer pointer] points to 0xbffff81c, which contains the char '
[integer pointer] points to 0xbffff820, which contains the char ' '
[char pointer] points to 0xbffff7f0, which contains the integer 1
[char pointer] points to 0xbffff7f1, which contains the integer 0
[char pointer] points to 0xbffff7f2, which contains the integer 0
[char pointer] points to 0xbffff7f3, which contains the integer 0
[char pointer] points to 0xbffff7f4, which contains the integer 2
答案 0 :(得分:15)
这就是指针aritmetics的工作方式:如果将指针递增1,则地址会增加指针类型的大小。因此,在你的机器中,int是4个字节,递增一个int指针会增加4个字节的地址。
答案 1 :(得分:9)
未定义的行为
你拥有的是undefined behavior,首先你违反了strict aliasing rule,这基本上使得通过不同类型的指针访问对象是非法的,尽管允许通过char *进行访问。我将引用我的answer here,其中更广泛地涵盖了这一点:
严格的别名规则,这使得访问对象成为非法 通过一个不同类型的指针,虽然通过char访问 * 被允许。允许编译器假设不同类型的指针不指向相同的内存并进行优化 因此。它还意味着代码调用未定义的行为和 真的可以做任何事情。
第二个不同的指针可能有不同的对齐要求,因此通过int指针访问char数组可能会违反此要求,因为char数组可能无法正确对齐int。 draft C99 standard部分涵盖了6.3.2.3
指针部分(强调我的):
使用指向对象或不完整类型的指针可以转换为 指向不同对象或不完整类型的指针。 如果结果 对于指向类型的指针,指针未正确对齐 57) 行为未定义。
clang
和以下标志-std=c99 -fsanitize=undefined -Wall -Wextra -Wconversion -pedantic
,使用正确的标志集的好编译器在这里应该有很多帮助我看到以下警告( see it live ):
warning: incompatible pointer types assigning to 'char *' from 'int [5]' [-Wincompatible-pointer-types]
char_pointer = int_array; // The char_pointer and int_pointer now
^ ~~~~~~~~~
warning: incompatible pointer types assigning to 'int *' from 'char [5]' [-Wincompatible-pointer-types]
int_pointer = char_array; // point to incompatible data types.
^ ~~~~~~~~~~
并且在运行时我看到以下错误:
runtime error: load of misaligned address 0x7fff48833df3 for type 'int', which requires 4 byte alignment
0x7fff48833df3: note: pointer points here
00 e0 3e 83 61 62 63 64 65 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6d 47 60 5a 1d 7f 00
^
Pointer arithmeic
因此指针算法基于所指向类型的大小。基本上syntactic sugar for pointer arithmetic的数组访问如何才能正常工作?您可以阅读更详细的说明here和related discussion here。
答案 2 :(得分:2)
在进行指针运算时,它将按照您尝试增加的大小递增。以此为例。
int a[2];
a[0] = 1;
a[1] = 3;
a = a + 1
printf("%d\n",*a) \\ 3
它需要按指向的东西的大小向前移动。总是帮助我的是首先将指针转换为char以使用字节。
int a[2];
a[0] = 1;
a[1] = 3;
a = (char)a + sizeof(int)*1
printf("%d\n",*a) \\ 3
这更容易理解,它会产生你的想法。