Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.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,我有以下代码。也许我没有像我应该理解的那样理解指针算法,但是为什么int_指针会增加4而不是1呢?对于char_指针,为什么它不增加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_指针会增加4而不是1呢?对于char_指针,为什么它不增加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;
    }
 }

指针算术就是这样工作的:如果指针增加1,地址就会增加指针类型的大小。因此,由于在您的计算机中,int是4个字节,因此增加int指针会增加4个字节的地址。

未定义的行为

首先,您违反了,这基本上使得通过不同类型的指针访问对象是非法的,尽管允许通过char*访问对象。我将引用我的文章,其中更广泛地介绍了这一点:

使访问对象非法的严格别名规则 通过不同类型的指针进行访问,但通过字符进行访问 *是允许的。允许编译器假设不同类型的指针不指向同一内存并进行优化 因此。它还意味着代码调用未定义的行为和 我真的可以做任何事

第二,不同的指针可能有不同的对齐要求,因此通过int指针访问字符数组很可能违反此要求,因为字符数组可能没有正确对齐int。第
6.3.2.3节
指针中介绍了这一点,其中指出(我的重点):

指向对象或不完整类型的指针可能会转换为 指向其他对象或不完整类型的指针如果结果为 指针未正确对齐57)对于指向的类型 行为未定义。

使用
clang
和以下标志
-std=c99-fsanitize=undefined-Wall-Wextra-Wconversion-pedantic
可以发现以下警告(),一个具有正确标志集的好编译器在这里应该会有很大帮助:

在运行期间,我看到以下错误:

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
             ^ 
指针算术


所以指针算法是基于被指向的类型的大小。否则,基本正常工作的阵列访问将如何进行?您可以阅读更详细的说明和。

当执行指针算术时,它将按您试图增加的大小递增。以此为例

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

这更容易理解,而且它会产生您所想的结果。

char\u pointer=int\u array这很糟糕。我认为分配不兼容类型的指针是未定义的行为。@ShafikYaghmour:OP在指针分配过程中混合了这些类型,但这不会改变指针的算术行为。尽管它违反了严格的别名。另一个问题是当
int\u指针
在后续循环迭代中被解引用时触发的越界数组访问。我遗漏了什么吗?@jweyrich此代码中有两种不同形式的未定义行为,如果不涵盖这些问题,这些问题就无法正确回答,因为代码不正确。@ShafikYaghmour:对,说得对。我将撤回我的投票并删除dup的评论+在你的答案上也是1:-)
char\u pointer=int\u数组--这不仅仅是未定义的行为,它还违反了约束。基本上这是非法的;任何符合要求的编译器都必须发出诊断,尽管许多编译器(不幸的是IMHO)会将其作为非致命警告。但如果您将其更改为
char\u pointer=(char*)int\u数组这不再是违反约束的行为,但根据使用指针的方式,您可能会遇到未定义的行为。
int\u pointer=char\u数组也是这样除了可能会遇到对齐问题之外。我认为数组的名称是一个常量ptr,其值不能更改。这里我认为行“a=a+1”应该给出编译错误。
int a[2];
a[0] = 1;
a[1] = 3;
a = a + 1
printf("%d\n",*a) \\ 3
int a[2];
a[0] = 1;
a[1] = 3;
a = (char)a + sizeof(int)*1
printf("%d\n",*a) \\ 3