我尝试创建一个多维数组并编写了一个函数但是当我检查我的矩阵时,我已经意识到我的指针的值是相同的,但它们的地址是不同的。为什么:)
#include <stdio.h>
#include <stdlib.h>
int **matrix(int a,int b){
int i;
int **x;
x = (int**)malloc(a * sizeof(int*));
for (i = 0; i < a; i++) {
x[i] = (int*)malloc(b * sizeof(int));
}
return x;
}
int main()
{
int **m1, **m2;
m1=matrix(3,3);
m2=matrix(3,3);
printf("Values: %d %d\n",m1[1][1],m2[1][1]);
printf("Addresses: %d %d",&m1[1][1],&m2[1][1]);
return 0;
}
答案 0 :(得分:1)
如果是m1 [1] [1],则表示您正在打印数组中的值。它们不是指针值。由于您尚未将它们初始化为任何值,因此它们可以是任何值。在你的情况下,他们正在变得相同
&amp; m1 [1] [1]是一个指针。由于您要分配两次内存,因此它们具有不同的值。 (阵列的不同地址)
答案 1 :(得分:0)
内存泄漏若隐若现!
首先,你有一个可能的内存泄漏程序。您正在为2 矩阵分配内存,但绝不会为您free
分配内存。你应该。堆上分配的所有内存都是您的责任,一旦您完成内存,就可以确保内存为free
。可能实现如下功能:
void free_matrix(int **matrix, int len)
{
if (matrix == NULL) return;//don't try and free NULL pointers
while(len--) free(matrix[len]);
free(matrix);
}
在打印出需要打印的内容后,在主函数中调用:
free_matrix(m1, 3);
m1 = NULL;//setting unused pointers to NULL is a good habit
free_matrix(m1,3);//won't cause problems
free_matrix(m2, 3);
free_matrix(m2, 1);//ERROR!
您也无法检查malloc
电话是否实际成功。如果没有足够的可用内存,malloc
将返回null,您应该处理此问题。至少做:
some_ptr = malloc(sizeof(*some_ptr));
if (some_ptr == NULL) exit(EXIT_FAILURE);//macro expands to 1
无论如何,我写了this codepad试图释放并重复分配相同的矩阵,直到内存中的值不同为止。事实证明,至少在键盘上,它们是相同的 我目前正在浏览linux内核代码和网络,看看是否有这样的原因。当内核空闲时,Linux可能会擦除堆内存,或者它可能是一个键盘操作...无论哪种方式,请继续关注更新:)
基本上,malloc
不会初始化它分配的内存。操作系统对freed内存的作用取决于操作系统。我在我的64位linux系统上尝试了下面的代码,使用
gcc -std=c99 -Wall src.c -o temp
它表明矩阵做包含不同的值,但在我的情况下大多是0
。无论如何,这是代码:
#include <stdio.h>
#include <stdlib.h>
void **matrix(int a,int b)
{
int i;
unsigned int **x;
x = malloc(a * sizeof(*x));
if (x == NULL) exit(EXIT_FAILURE);
for (i = 0; i < a; i++)
{
x[i] = malloc(b * sizeof(*(x[i])));
if (x[i] == NULL) exit(EXIT_FAILURE);
}
return (void **)x;
}
void free_matrix(void ***m, int l)
{
if (*m == NULL) return;
while(l--) free((*m)[l]);
free(*m);
*m = NULL;
}
int main( void )
{
unsigned int **m1, **m2, c=0;
m1 = (unsigned int **) matrix(3,3);
m2 = (unsigned int **) matrix(3,3);
printf("%lu <> %lu\n", sizeof(m1[1][1]), sizeof(m1));//4 <> 4 -> 32 bit, 4 <> 8 -> 64
while(*(m1[1]+1) == *(m2[1]+1) && c < 101)
{
++c;
free_matrix((void ***) &m1,3);
m1 = (unsigned int **) matrix(3,3);
}
if (c == 101)
{
for(c=0;c<3;++c) printf("%u %u %u\n%u %u %u\n\n",*(m1[c]), *(m1[c]+1), *(m1[c]+2),*(m2[c]), *(m2[c]+1), *(m2[c]+2));
}
else
{
printf("Different vals after %d tries\n", c);
}
printf("Values: %u %u %c\n",m1[1][1],m2[1][1], (unsigned char) m1[1][1]);
printf("Addresses: %p %p\n",(void *) (m1[1]+1), (void *) (m2[1]+1));
free_matrix((void ***)&m1, 3);
free_matrix((void ***)&m2,3);
return 0;
}
我得到的输出示例如下:
4 8 12546112 0 0 0 0 0 12546144 0 0 0 0 0 0 0 0 0 0 0 Values: 0 0 Addresses: 0xbf7054 0xbf70d4
要获得实际的地址,您必须写:
printf("Addresses: %p, %p\n", (void *) &m1[1][1], (void *)&m1);
相反:
printf("Addresses: %d %d",&m1[1][1],&m2[1][1]);
因为m1[1][1]
不是指针! m1
是指向int的指针,因此m[1]
是指向int的指针,m1[1][1]
是int ,而不是指针。< / p>
哦,并且没有完成malloc
的返回值。它隐藏了可能的错误,malloc
将返回兼容的指针类型或NULL
。
但为什么他们的地址不一样?很简单:你要分配2个独立的堆内存块。你没有两次分配相同的内存(这是不可能的) 您正在尝试打印出存储在堆中两个不同位置的值的地址。
这就像建造两栋完全相同的房屋,只有你在不同的城市建造它们。他们的地址将是独一无二的。
值相同的事实是巧合。 malloc
不会更改内存的内容,因此如果内存块自上次使用后恰好设置为0
,那么您将会遇到零初始化内存,但你无法确定这种情况总是如此......你应该问的问题不是为什么,而是为什么不或赔率是多少