小编Abh*_*osh的帖子

为什么我不能通过这个指针黑客找到元素大小?

请考虑以下C语言

int arr[]= {1,2,3,4,5};
Run Code Online (Sandbox Code Playgroud)

我的系统使用4个字节来存储int数据.现在&arr[0] => 0022FEB0&arr[1]=>0022FEB4运行的那一刻

现在

int diff=&arr[1]-&arr[0];
Run Code Online (Sandbox Code Playgroud)

存储在DIFF值1而不是4.

为什么?

c arrays pointers

6
推荐指数
1
解决办法
174
查看次数

为什么指针在C中找不到数组的大小,在被调用的函数中使用时给出不同的值

这是下面的代码来说明问题:

#include <stdio.h>

void func(int arr[]);

int main() {
    int arr[10];
    int n = *(&arr + 1) - arr;
    printf("%d\n", n);
    func(arr);
    return 0;
}

void func(int arr[]) {
    int n = *(&arr + 1) - arr;
    printf("%d\n", n);
}
Run Code Online (Sandbox Code Playgroud)

上述代码的输出是:

10
268435906
Run Code Online (Sandbox Code Playgroud)

c arrays function

5
推荐指数
2
解决办法
97
查看次数

在源程序的中间表示中“间接三元组”比“四元组”更有优势

考虑作业,a := b*-c + b*-c.

四人间

图 1 上述语句的四元组

以下是红龙书的摘录。

如果多次使用相同的临时值,则间接三元组与四元组相比可以节省一些空间。原因是语句数组中的两个或多个条目可以指向结构的同一行op-arg1-arg2。例如,下图中的行(14)(16)可以组合,然后我们可以组合(15)(17)

三地址语句的间接三重表示

图2 三地址语句的间接三重表示

我的问题是摘录中关于使用间接三元组节省空间的内容,我们也可以对四元组说同样的话,如下:

优化

我们可以将语句的三地址代码写为右侧的代码,而不是上图中左侧的代码...然后我们将得到下面的四元组:

改良四联

这正是摘录中关于间接三元组相对于四元组的优势的内容。

那么我们可以得出什么结论呢?

compiler-construction intermediate-language

5
推荐指数
0
解决办法
991
查看次数

当函数原型有一个声明为 int a[][10] 的参数时,编译器会将其视为 int (*a)[10] 吗?

我听到很多人说,当我们想要将一维数组传递给函数时,fun以下原型是等效的:

\n

1.

\n
   int fun(int a[]);\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. \n
\n
   int fun(int a[10]);\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. \n
\n
   int fun(int *a);\n
Run Code Online (Sandbox Code Playgroud)\n

我什至听到人们说第一个和第二个在 C 中内部转换为第三个。我猜这是真的,因为sizeof(a)在 2 中声明的函数的定义中执行某些操作会给出指针的大小(以字节为单位)(而不是 10*sizeof(int))。

\n

话虽这么说,我已经看到一些文本声称将 2D 数组传递给函数,以下内容是等效的:

\n

1.

\n
int fun(int a[][10]);\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. \n
\n
int fun(int (*a)[10]);\n
Run Code Online (Sandbox Code Playgroud)\n

在这里我再次听到人们说在 C 中第一个在内部转换为第二个。如果这是真的,那么下面的内容应该是等价的,对吗?

\n

1.

\n
int fun(int a[][]);\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. \n
\n
int fun(int (*a)[]);\n
Run Code Online (Sandbox Code Playgroud)\n

但不幸的是,第一个提出了编译错误,但第二个没有:

\n
    1 | int fun(int a[][]);\n      |             ^\nt.c:2:13: note: declaration of \xe2\x80\x98a\xe2\x80\x99 …
Run Code Online (Sandbox Code Playgroud)

c arrays

5
推荐指数
1
解决办法
129
查看次数

malloc()在哪里分配内存?是进程虚拟地址空间的数据段还是堆段?

自从我被介绍到 以来C,我就被告知C动态内存分配是使用家族中的函数完成的malloc。我还了解到,动态分配的内存malloc是在进程的堆部分分配的。

在此输入图像描述

各种操作系统教科书都说这malloc涉及系统调用(虽然并不总是但有时)来将堆上的结构分配给进程。现在假设malloc返回指向堆上分配的字节块的指针,为什么它需要系统调用。函数的激活记录放置在进程的堆栈部分中,并且由于“堆栈部分”已经是进程虚拟地址空间的一部分,所以激活记录的压入和弹出、堆栈指针的操作,只需从虚拟地址空间的最高可能地址。它甚至不需要系统调用。

现在基于同样的理由,由于“堆部分”也是进程虚拟地址空间的一部分,为什么需要系统调用来在该部分中分配字节块。像这样的例程malloc可以自行处理“空闲”列表和“已分配”列表。它需要知道的只是“数据部分”的结尾。某些文本说系统调用对于“将内存附加到进程以进行动态内存分配”是必要的,但是如果malloc在“堆部分”上分配内存,为什么需要在 期间将内存附加到进程malloc?可以简单地取自过程中已经一部分的部分。

在阅读 Kernighan 和 Ritchie 的《C 编程语言》[2e] 文本时,我发现了他们对该malloc函数的实现 [第 8.7 节第 185-189 页]。作者说:

malloc根据需要调用操作系统获取更多内存。

这就是操作系统文本所说的,但与我上面的想法相反(如果malloc在堆上分配空间)。

由于向系统请求内存是一项相对昂贵的操作,因此作者不会在每次调用 时都这样做,因此他们创建了一个至少请求单位的malloc函数;这个较大的块根据需要被切碎。而基本的空闲列表管理是由.morecoreNALLOCfree

但问题是作者使用sbrk()向操作系统请求内存morecore。现在维基百科说:

brk和是 Unix 和类 Unix 操作系统中使用的基本内存管理系统调用,用于控制分配给进程数据段sbrk的内存量。

在哪里

数据段(通常表示为.data)是目标文件或程序的相应地址空间的一部分,其中包含初始化的静态变量,即全局变量和静态局部变量。

我猜这不是“堆部分”。[数据部分是上图中从下数第二部分,而堆是从下数第三部分。]


我完全困惑了。我想知道到底发生了什么以及这两个概念如何正确?请通过将分散的碎片连接在一起来帮助我理解这个概念......

c malloc memory-management heap-memory sbrk

3
推荐指数
1
解决办法
4332
查看次数

洞察错误"初始化元素不是常数"

看下面的代码......我收到了行号的错误.6 ...请任何人解释为什么会发生这种情况?

#include<stdio.h>

struct test{
    int data;
};

typedef struct test* Test;

Test obj=(Test) calloc(1,sizeof(struct test));

int main()
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

c

2
推荐指数
1
解决办法
42
查看次数

词汇错误:标识符拼写错误

在《龙书》中提到“词汇错误包括标识符的拼写错误。例如,拼写错误ellispeSizeelipseSize

我无法理解这是怎么回事(词法分析器可以识别拼写错误的标识符并导致错误)。和ellipseSize都是elipseSize有效的标识符词位。所以词法分析阶段应该没有问题。可能在编译的后期阶段,我们将了解到elipseSize尚未定义......

compiler-construction compiler-errors lexical

1
推荐指数
1
解决办法
490
查看次数