简体   繁体   English

C编程中的整数数组

[英]array of integers in c programming

I have this homework at school where I have to evaluate what is the output to the following code: 我在学校有这项作业,在这里我必须评估以下代码的输出是什么:

#include<stdio.h>
int main()
{
    int a[2][2] = {1, 2, 3, 4};
    int i, j;
    int *p[] = {(int*)a, (int*)a+1, (int*)a+2};
    for(i=0; i<2; i++)
    {
        for(j=0; j<2; j++)
        {
            printf("%d, %d, %d, %d\n",
              *(*(p+i)+j), *(*(j+p)+i),
              *(*(i+p)+j), *(*(p+j)+i));
        }
    }
    return 0;
}

the output is: 输出为:

1,1,1,1
2,2,2,2
2,2,2,2,
3,3,3,3

What I didn`t study, yet I have it as a homework, are these lines: 我没有学习,但作为作业却有这些内容:

int a[2][2] = {1, 2, 3, 4};
int *p[] = {(int*)a, (int*)a+1, (int*)a+2};

I also don't understand what is the difference between *(*(p+i)+j) and *(*(i+p)+j) . 我也不明白*(*(p+i)+j)*(*(i+p)+j)什么区别。 Thank you. 谢谢。

Actually you need to understand the how compiler seeing the array. 实际上,您需要了解编译器如何看待数组。 as you have mentioned *(*(p+i)+j) and *(*(i+p)+j) 正如您提到的*(*(p+i)+j)*(*(i+p)+j)

Actually Compiler see *(*(p+i)+j) as *(*(address of P + number of increment in memory block)+number of increment in memory block) 实际上编译器将*(*(p+i)+j)视为*(*(address of P + number of increment in memory block)+number of increment in memory block)

suppose p is the base address with value 5000 and i=2, j=3 假设p是值为5000的基地址且i = 2,j = 3

*(*(p+i)+j) = *(*(5000+2)+3) = *(*(5008)+3) *(*(p+i)+j) = *(*(5000+2)+3) = *(*(5008)+3)

*(*(i+p)+j) = *(*(2+5000)+3) = *(*(5008)+3) *(*(i+p)+j) = *(*(2+5000)+3) = *(*(5008)+3)

As you can see both the result came same. 如您所见,两个结果都相同。 I have supposed compiler assigned integer as 4 byte. 我假设编译器将整数分配为4个字节。 Hope this will help you. 希望这会帮助你。

int a[2][2] = {1, 2, 3, 4};

That is a horrible way of writing int a[2][2] = {{1, 2}, {3, 4}}; 那是写int a[2][2] = {{1, 2}, {3, 4}};一种可怕方法int a[2][2] = {{1, 2}, {3, 4}};

It is a 2d array of numbers. 它是一个二维数组。 Hence, a may be interpreted to be a pointer to it's first element, ie the address of {1, 2}. 因此, a可被解释为是一个指向它的指针的第一个元素,即{1,2}的地址。 In the same way, a + 1 is the address of {3, 4}. 同样, a + 1是{3,4}的地址。

int *p[] = {(int*)a, (int*)a+1, (int*)a+2};

That is parsed as int *p[] = {(int*)a, (int*)(a+1), (int*)(a+2)}; 解析为 int *p[] = {(int*)a, (int*)(a+1), (int*)(a+2)};

Nope it is actually ((int*)a)+1 and so on. 不,它实际上是((int*)a)+1 ,依此类推。

Each cast (int*) converts a from a pointer to the array {1, 2} to a pointer to the int 1. 每个强制转换(int *)将a从指向数组{1,2}的指针转换为指向int 1的指针。

It fills an array of int* with the addresses of the first int's in the three two dimensional arrays at a , a + sizeof(int[2]) and a + 2 * sizeof(int[2]) . 它使用 a两个二维数组中的第一个int的地址填充一个int *的数组,即 a + sizeof(int[2])a + 2 * sizeof(int[2]) The third is nonexistent, being a pointer 'past the end'. 第三个不存在,是“过去”的指针。

It fills the array with poiinters to 1, 2, 3 even though a is not a 1 dimensional array. 即使a不是一维数组,它也会用poiinters填充数组至1,2,3。

All of these are the same. 所有这些都是一样的。

*(*(p+i)+j), *(*(j+p)+i),
*(*(i+p)+j), *(*(p+j)+i));

That is (p + i) == (i + p) (cummutativity) and (*(j+p)+i) == p[j][i] and (*(p+i)+j) == p[i][j] . (p + i) == (i + p) (累积性)和(*(j+p)+i) == p[j][i](*(p+i)+j) == p[i][j] But p[x][y] == *((int*)a + x) + y) == a[x + y] So p[j][i] == p[i][j] == (a[i + j]) 但是p[x][y] == *((int*)a + x) + y) == a[x + y]所以p[j][i] == p[i][j] == (a[i + j])

*(array_name + i) in C is primarily used to confuse people when array_name[i] is perfectly understandable. 当完全可以理解array_name[i]时,C中的*(array_name + i)主要用于使人们array_name[i]困惑。

You're touching on multi-dimensional arrays, pointers, and double dereferencing: either you're a few months (maybe closer to a year behind) or your teacher's hoping to shock you into taking the class seriously (many people assume CS classes will be easy). 您正在接触多维数组,指针和双重取消引用:是您几个月之后(也许比现在晚一年),或者您的老师希望您震惊地认真对待这门课(许多人认为CS课会放轻松)。 Or maybe she's a sadist. 也许她是个虐待狂。 Hard to tell, really. 真的很难说。

"I also don't understand what is the difference between ( (p+i)+j) and ( (i+p)+j)" There is no difference. “我也不明白 (p + i)+ j)和 (i + p)+ j)有什么区别”没有区别。 That is why each line of output repeats the same number. 这就是为什么输出的每一行都重复相同的数字。 Each line evaluates to the same thing mathematically. 每行在数学上对同一事物进行求值。 I think this is an attempt to demonstrate that a pointer is just a number. 我认为这是为了证明指针只是一个数字。

I'll try to explain this plainly: memory is a contiguous sequence of data. 我将尝试对此进行简单地解释:内存是连续的数据序列。 Your first line demonstrates this. 您的第一行演示了这一点。 int a[2][2] = {1, 2, 3, 4}; 整数a [2] [2] = {1,2,3,4}; focus on the last part {1, 2, 3, 4} This is literally a list of data. 专注于最后一部分{1,2,3,4}这实际上是数据列表。 The first data is 1, the second is 2, the third is 3, etc. You could just as easily reverse this - the data doesn't have to match the sequence at all. 第一个数据为1,第二个为2,第三个为3,依此类推。您可以轻松地将其取反-数据完全不必与序列匹配。 For example, {100, 43, 512, -1} would have produced the output: 例如,{100,43,512,-1}将产生输出:

100, 100, 100, 100 43, 43, 43, 43 512, 512, 512, 512 -1, -1, -1, -1 And, in your computer's memory, these are stored contiguously; 100,100,100,100 43,43,43,43 512,512,512,512 -1,-1,-1,-1并且它们连续存储在您的计算机内存中; right one after another. 接二连三。

Now, in what is typically considered bad form, your teacher chose to define this single list as a list of two lists (in CS terms, an array of two arrays). 现在,以通常被认为是不好的形式,您的老师选择将单个列表定义为两个列表的列表(以CS术语来说,是两个数组的数组)。 a[2][2] is fundamentally the same as stating "a is an array of two arrays with two elements each", or "I've got two lists with two things on them". a [2] [2]从根本上说“ a是两个数组,每个数组包含两个元素”或“我有两个包含两个东西的列表”。

Because all memory is contiguous, both of those arrays are contiguous with eachother. 因为所有内存都是连续的,所以这两个数组都是连续的。 In memory, it is the same as if the second array was just added to the end of the first array. 在内存中,就好像第二个数组刚刚添加到第一个数组的末尾一样。 Which is why you can have two arrays of two elements each represented as one array of four elements (2 * 2 = 4). 这就是为什么您可以拥有两个元素组成的两个数组,每个元素表示为四个元素组成的数组(2 * 2 = 4)。

Another way she could have written that line is: int a[2][2] = { { 1, 2 }, { 3, 4 } }; 她写那行的另一种方式是:int a [2] [2] = {{1,2},{3,4}}; or int a[4] = { 1, 2, 3, 4 }; 或int a [4] = {1,2,3,4}; or int a[] = { 1, 2, 3, 4 }; 或int a [] = {1,2,3,4};

I assume you at least understand a little bit about coding, so I won't insult you with explaining i and j or the loops. 我假设您至少对编码有所了解,所以我不会侮辱您解释i和j或循环。

...which leaves this gem: ...留下了这个宝石:

int *p[] = {(int*)a, (int*)a+1, (int*)a+2};

'p' is what we'd call an array of pointers. 'p'是我们称为指针数组的东西。 Pointers are a number that represents a location in memory. 指针是代表内存中位置的数字。 All memory is contiguous. 所有内存是连续的。 That means that if you started at the first "int" that could be stored in memory, and moved forward an int at a time until you got to the pth int, you would be at the place in memory p represents. 这意味着,如果您从可能存储在内存中的第一个“ int”开始,并且一次向前移动一个int直到到达pth int,那么您将位于内存中p所代表的位置。 We call them pointers because they "point" into memory. 我们称它们为指针是因为它们“指向”内存。 Also, arrays are pointers too. 同样,数组也是指针。 "a" points to its first element. “ a”指向其第一个元素。 so we could rewrite that first line again: 因此我们可以再次重写第一行:

int *a = { 1, 2, 3, 4 };

(disclaimer: it may not compile, never seen code written like that before, but it's basically what we already do for text.) and the third line can be rewritten like this: (免责声明:它可能无法编译,以前从未见过像这样编写的代码,但是基本上这是我们已经对文本进行的操作。)并且第三行可以这样重写:

int *p[] = (int *)a;

hope I explained it to you well enough! 希望我对你解释得足够好!

also, tell your teacher that code like this would not even be acceptable if accompanied by a series of comically depressing and apologetic comments that also explain why it was decided to write the code in this way, and that you would be better served being shown code acceptable for use in the real world rather than this academic nonsense. 另外,告诉您的老师,如果这样的代码带有一系列令人沮丧且令人歉意的注释,这些注释也可以解释为什么决定以这种方式编写代码,那将是不可接受的,并且最好向您显示代码可以在现实世界中使用,而不是在学术上胡说八道。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM