如何写入我有pnumber[2%4][2%4]
的 2D 指针,以及如何显示具有 3 个以上密码的pnumber
?
我正在制作一个程序来用 C 编写帕斯卡三角形。 当指针pnumbers[i][j]
同时具有i
和j = 2 mod 4
时,除了 i 和j = 2
,那么我的程序不会写入地址并给出错误消息:
pascals triangle: malloc.c:2406: sysmalloc: Assertion '{old_top == initial_top (av) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed.
Aborted.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int factorial(int p) {
if (p>=1) {
return p*factorial(p-1);
}
else {
return 1;
}
}
int NchooseM(int n, int m) {
return factorial(n)/(factorial(n-m)*factorial(m));
}
int main() {
int n =7;
int x = n-2;
int i, j, k;
/*
printf("How many rows of Pascals triangle do you want to write?n");
scanf("%d", &n);
*/
int **pnumbers;
pnumbers = (int **) malloc(n *sizeof(int *));
/* Allocate memory for storing the individual elements in a row */
for (i = 0; i < n; i++) {
pnumbers[i] = (int *) malloc(i * sizeof(int));
}
pnumbers[0][1] = 1;
/* Calculating the value of pnumbers[k][l] */
for (i = 0; i < n; i++) {
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
/*
if (!(i % 4 == 2 && i != 2))
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
} else if (i > 2) {
for (j = 0; j <= i-1; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
}
*/
}
/* Writing out the triangle */
for (i = 0; i < n; i++) {
for (k = 0; k <= x; k++){
printf(" ");
}
for (j = 0; j <= i; j++) {
printf("%d ", pnumbers[i][j]);
}
x = x-1;
printf("n");
}
for (i = 0; i < n; i++) {
free(pnumbers[i]);
}
free(pnumbers);
return 0;
}
当我避免写入这些地址并将它们打印出来时,我会在这些内存地址处得到一些看似随机的整数。 此外,当避免这些地址并打印出如此多的行时,我得到了一些具有更高整数且超过 3 个虹吸管的点,它似乎溢出了 - 我看不到它背后的逻辑。 运行第二个代码的结果
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int factorial(int p) {
if (p>=1) {
return p*factorial(p-1);
}
else {
return 1;
}
}
int NchooseM(int n, int m) {
return factorial(n)/(factorial(n-m)*factorial(m));
}
int main() {
int n =20;
int x = n-2;
int i, j, k;
/*
printf("How many rows of Pascals triangle do you want to write?n");
scanf("%d", &n);
*/
int **pnumbers;
pnumbers = (int **) malloc(n *sizeof(int *));
/* Allocate memory for storing the individual elements in a row */
for (i = 0; i < n; i++) {
pnumbers[i] = (int *) malloc(i * sizeof(int));
}
pnumbers[0][1] = 1;
/* Calculating the value of pnumbers[k][l] */
for (i = 0; i < n; i++) {
/*
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
*/
if (!(i % 4 == 2 && i != 2))
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
} else if (i > 2) {
for (j = 0; j <= i-1; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
}
}
/* Writing out the triangle */
for (i = 0; i < n; i++) {
for (k = 0; k <= x; k++){
printf(" ");
}
for (j = 0; j <= i; j++) {
printf("%d ", pnumbers[i][j]);
}
x = x-1;
printf("n");
}
for (i = 0; i < n; i++) {
free(pnumbers[i]);
}
free(pnumbers);
return 0;
}
但是第 13 行仍然很混乱。
代码遇到溢出int
因此出现未定义的行为(UB(。
对于 32 位int
和int factorial(int p)
,p > 12
在int
范围内流动。
代码可以使用更宽的整数类型(long long
最多可以工作p==20
(,但可以在NchooseM()
进行改进,以避免更高值的溢出。
像下面这样。 工作温度可达int n = 30;
int NchooseM(int n, int m) {
// return factorial(n)/(factorial(n-m)*factorial(m));
int nm = 1;
int den = 1;
for (int i = m+1; i <= n; i++) {
assert(INT_MAX/i >= nm);
nm *= i;
assert(nm % den == 0);
nm /= den++;
}
return nm;
}
尝试unsigned long long
并工作到int n = 62;
编辑:另一个错误:
我通过将全部初始化为 1 来"修复",但我怀疑/* Calculating the value of pnumbers[k][l] */ for (i = 0; i < n; i++) {
代码中仍然存在问题。
pnumbers[i] = malloc((i + 1) * sizeof pnumbers[i][0]);
for (int j = 0; j < i + 1; j++) {
pnumbers[i][j] = 1;
}
旁白:与其pnumbers[i] = (int *) malloc((i+1) * sizeof(int));
,不如考虑下面,不要进行不必要的演员转换,也没有尝试匹配正确的类型。
pnumbers[i] = malloc(sizeof pnumbers[i][0] * (i+1));