关于数组是“的困惑”;“归零”; #包括 #包括 静态charmem[4]; int main() { int*A=(int*)(mem); mem[0]=0; mem[1]=1; mem[2]=2; mem[3]=3; int i; A[0]=5; 对于(i=0;i

关于数组是“的困惑”;“归零”; #包括 #包括 静态charmem[4]; int main() { int*A=(int*)(mem); mem[0]=0; mem[1]=1; mem[2]=2; mem[3]=3; int i; A[0]=5; 对于(i=0;i,c,arrays,C,Arrays,,因为在您的系统中,sizeof int至少是sizeof(char)的4倍,所以需要4字节来覆盖您编写的所有内容,因为A是指向int的指针(但可能需要更大的时间)(这是典型的情况)如果不是,则是未定义的行为 还要注意的是,我们写它的方式取决于endianness。在你的例子中,它是little endianness。因此,基于endianness,它可能也会有所不同。不管怎样,这仅仅是为了实验 另外,为了让您了解当sizeof(int)大于4时为什么为UB,您可以通过A[0]访问从该数组内存中

,因为在您的系统中,
sizeof int
至少是
sizeof(char)
4倍,所以需要
4
字节来覆盖您编写的所有内容,因为
A
是指向
int
的指针(但可能需要更大的时间)(这是典型的情况)如果不是,则是未定义的行为

还要注意的是,我们写它的方式取决于endianness。在你的例子中,它是little endianness。因此,基于endianness,它可能也会有所不同。不管怎样,这仅仅是为了实验


另外,为了让您了解当
sizeof(int)
大于
4
时为什么为UB,您可以通过
A[0]访问
从该数组内存中取出一些内存,并尝试对其进行修改和更改-导致未定义的行为。

因为在您的系统中,
sizeof int
至少是
sizeof(char)的
4倍
因此需要
4
字节来覆盖您编写的所有内容,因为
A
是指向
int
的指针(但可能需要大于该值)(通常情况下是这样),如果不是,则是未定义的行为

还要注意的是,我们写它的方式取决于endianness。在你的例子中,它是little endianness。因此,基于endianness,它可能也会有所不同。不管怎样,这仅仅是为了实验

另外,为了让您了解当
sizeof(int)
大于
4
时它为什么是UB,您可以通过
A[0]
从该数组内存中访问一些内存,并尝试修改它并对其进行更改,从而导致未定义的行为。

#include<stdio.h>
#include<stdlib.h>

static char mem[4];

int main()
{
    int* A = (int*)(mem);

    mem[0] = 0;
    mem[1] = 1;
    mem[2] = 2;
    mem[3] = 3;

    int i;
    A[0] = 5;

    for (i = 0; i<4; i++)
    {
        printf("%d\t", mem[i]);
    }

    printf("\n");
    return 0;
}
5
写入整数,其大小大于
char
(2,4,8,视情况而定)

您的系统似乎是little endian,因此在第一个
char
位置写入5,然后写入0

请注意,如果
sizeof(int)
为8(在某些系统上可能会发生这种情况),则代码是不安全的,并且会触发未定义的行为,因为它会覆盖超过
mem
阵列的内存(更不用说可能出现的未对齐问题,这些问题可能会降低操作速度,甚至会导致某些处理器崩溃)

这就是为什么我们必须尊重规则,以避免“欺骗编译器”,例如,创建一个
联合
,以便编译器可以调整对齐和检查大小

这另一个问答是相关的:

在你的情况下

#include<stdio.h>
#include<stdlib.h>

static char mem[4];

int main()
{
    int* A = (int*)(mem);

    mem[0] = 0;
    mem[1] = 1;
    mem[2] = 2;
    mem[3] = 3;

    int i;
    A[0] = 5;

    for (i = 0; i<4; i++)
    {
        printf("%d\t", mem[i]);
    }

    printf("\n");
    return 0;
}
5
写入整数,其大小大于
char
(2,4,8,视情况而定)

您的系统似乎是little endian,因此在第一个
char
位置写入5,然后写入0

请注意,如果
sizeof(int)
为8(在某些系统上可能会发生这种情况),则代码是不安全的,并且会触发未定义的行为,因为它会覆盖超过
mem
阵列的内存(更不用说可能出现的未对齐问题,这些问题可能会降低操作速度,甚至会导致某些处理器崩溃)

这就是为什么我们必须尊重规则,以避免“欺骗编译器”,例如,创建一个
联合
,以便编译器可以调整对齐和检查大小


另一个问题与解答是相关的:

当您试图使用
int
指针来别名
char*
类型时,代码表现出未定义的行为。这违反了严格的别名规则,因此您的代码完全是错误的


char*
类型可以别名其他指针类型,但不能反过来。因此,请确保不要违反语言的约束。

当您尝试使用
int
指针别名
char*
类型时,您的代码表现出未定义的行为。这违反了严格的别名规则,因此您的代码只是一个错误好的

一个
char*
类型可以别名其他指针类型,但不能反过来。因此,请确保不要违反语言的约束。

int*A=(int*)(mem);
-->如果 结果指针未与引用类型正确对齐,行为未定义。“C11dr§6.3.2.3 7

所以剩下的代码是没有意义的

使用
联合
处理对齐和抗锯齿问题

A[0] = 5;
原因:现在代码中删除了未定义的行为UB, 好答案解释了这些差异。

int*A=(int*)(mem);
-->如果 结果指针未与引用类型正确对齐,行为未定义。“C11dr§6.3.2.3 7

所以剩下的代码是没有意义的

使用
联合
处理对齐和抗锯齿问题

A[0] = 5;
原因:现在代码中删除了未定义的行为UB,
很好的答案解释了差异。

char
int
的大小不一样。编写
A
的第一个元素会写入
mem
的所有4个元素,因为您编写的代码违反了语言约束,并导致了一些未定义的行为。替换为
A[0]=123456789;
使其更直观易懂。
int*A=(int*)(mem);
-->根据“如果结果指针未正确对齐引用的类型,则行为未定义”的风险C11dr§6.3.2.3 7祝贺您,您发现了小端存储。
char
int
的大小不一样。编写
A
的第一个元素将写入
mem
的所有4个元素,因为您编写的代码违反了语言约束,并导致了一些未定义的行为。替换为
A[0]=123456789;
使其更直观易懂。
int*A=(int*)(mem);
-->如果