空数组如何包含在计算中?

时间:2019-01-26 22:43:49

标签: c

#include <stdio.h>

int f( int *x ) {
    *x = 35;
}

int main( int argc, char *argv[] ) {
    int p[32];
    int *q = p + 5;

    f( q );

    printf( "%d", p[5] );

    return 0;    
}

能否请您解释为什么输出为35?

我尝试使用printf("%d", p)输出p的值,并在int p[32]之后立即返回-2077686688

我认为这仅仅是因为我还没有为p[32]数组分配任何值,所以它只返回了一个随机数。

但是,最让我困惑的部分是*q = p + 5

数组如何做到这一点?

由于p数组中没有值,如何才能在此表达式中返回其大小?

3 个答案:

答案 0 :(得分:3)

在您的代码中,int p[32]预留了一个大小为32的数组,可以使用p进行引用。当您将q定义为p + 5时,就是将q分配为指向p指向的内存中第6个(1索引)元素的指针。

当您将q传递到f()时,q处的值将从之前的值(未初始化的内存)设置为35。由于q指向与p[5]相同的位置,因此p[5]将是35,因为这是f()在内存中设置的值。

答案 1 :(得分:0)

C是一种低级编程语言,通过C变量使用内存的行为可能会使来自具有较高抽象级语言的程序员感到困惑。

让我们首先分解您的main函数。

int p[32];

在程序中调用函数时,会将其分配给分配给进程的RAM中的某个部分。此部分称为堆栈。通过此语句,您告诉编译器您的函数(main)需要用于堆栈中32个整数的空间。您使用变量p所做的其他声明将在为32个整数保留的该空间上进行操作。

请注意,您没有告诉编译器有关如何初始化为p分配的这部分内存的任何信息。因此,分配给32个整数的所有这些字节将存储调用函数之前包含的所有字节。

让我们看看下一个。

int *q = p + 5;

这非常相似,但是现在您正在堆栈中请求一些内存,其大小可以适合“指向整数的指针”。指针是裸露的“带有类型的内存地址”的C抽象。因此,该空间将用于在内存中存储地址,这些地址将引用RAM中用于存储整数的另一个空间。

您还告诉编译器使用q的值初始化p + 5的堆栈空间。与上面的32个整数(p的空格不同,q的空格将在调用函数后立即初始化。

表达式p + 5正在应用所谓的“指针算术”。这用于获取RAM中的地址,并根据需要的偏移量上下移动。请记住,p是一个数组,C中的数组在参与指针算术时就像指针(地址)一样工作。因此,p + 5的真正含义是“第一个地址p指向后的5个整数的地址”。最终是“指向p第六个元素的指针(第一个是p[0]),换句话说,就是p[5]的地址。

f(q);

在此语句中,您要传递存储在q中的地址,该地址恰好是p中第六个元素的地址。返回的函数f35分配给该地址指向的RAM中的位置,因此将p[5]将访问的整数更改为35的整数。

此时,p[5]p中唯一具有初始化值的元素。 p中的所有其他整数将继续存储它们在程序初始化期间调用main之前所持有的内容。

printf( "%d", p[5] );

当执行返回到main时,p[5]可以访问的整数现在设置为35,而这正是您希望通过此{{ 1}}语句。

答案 2 :(得分:-1)


int main() {
    int p[32] = { 0 };
    // initializing array with zeros; no mode random values in array!

    int *q = p + 5;

    if (&p == &p[0] && &3[p] == &p[3]) {
        printf("Sick sad C world\n");
    }
    /* We can say that there's no such thing as 'array' in C!
     * (actually, C has arrays)
     * but C arrays are 'thin layer'; try to compare JS Array and C Arrays
     * See this: https://stackoverflow.com/a/381549/10972945
     * So: p[0] == *(p + 0) == *p
     * 'Array' is an address of it's zero element! */

    printf(
        "p located at %p\n"
        "p + 1 located at %p\n"
        "p + 5 located at %p\n"
        "Size of int (in bytes) is %zu\n",
        (void*) p,
        (void*) (p + 1),
        (void*) (p + 5),
        sizeof(int) 
    );
    /*  Try to run this code and substract addresses, one from another.

            p located at 0x7ffee3e04750
            p + 1 located at 0x7ffee3e04754
            p + 5 located at 0x7ffee3e04764
            Size of int (in bytes) is 4

        See:
        address of (p + 1) - address of p
            == 0x7ffee3e04754 - 0x7ffee3e04750
            == 4 == sizeof(int)
        address(p + 5) - address(p)
            == 0x7ffee3e04764 - 0x7ffee3e04750
            == 0x14 == 20 == 5 * sizeof(int)
     */
}