C 我们怎么能这样说;int i";是定义也是声明
以下是Dennis Ritchie C编程书中的直接内容: 声明是指声明变量性质但未分配存储的位置。定义是指在存储中创建或分配变量的位置C 我们怎么能这样说;int i";是定义也是声明,c,declaration,definition,C,Declaration,Definition,以下是Dennis Ritchie C编程书中的直接内容: 声明是指声明变量性质但未分配存储的位置。定义是指在存储中创建或分配变量的位置 问题 “创建变量”和“声明变量”之间的区别到底是什么 在下面的程序中,变量j刚刚声明,没有定义,所以为什么没有编译错误,因为我们正在将j的地址值分配给I,而变量j尚未分配存储(编译期间) int*I,j是声明还是定义?我得到的是,这是一个定义。但在这本书中,它既是宣言又是定义 我对林克和里奇书中给出的两个截然不同的概念感到困惑 请说明我错在哪里?是否值分配
问题 “创建变量”和“声明变量”之间的区别到底是什么 在下面的程序中,变量
j
刚刚声明,没有定义,所以为什么没有编译错误,因为我们正在将j
的地址值分配给I
,而变量j
尚未分配存储(编译期间)
int*I,j
是声明还是定义?我得到的是,这是一个定义。但在这本书中,它既是宣言又是定义
我对林克和里奇书中给出的两个截然不同的概念感到困惑
请说明我错在哪里?是否值分配被推迟到运行时,并且在运行时变量
j
被分配为垃圾值,因此没有错误?声明声明变量的类型(这也有助于确定它需要多少空间)
定义说明变量的类型,并为变量分配空间
是的,每个定义都是一个声明 这是一项声明:
extern int j;
在这个声明之后,编译器知道j
的类型是int
。在这个声明之后,我们可以说
printf("%d\n", j);
我们可以这样说,编译器不会抱怨(至少,它不会马上抱怨),因为至少目前,编译器拥有它所需要的所有信息
但是,如果我们试图编译这个完整的程序:
#include <stdio.h>
extern int j;
int main()
{
printf("%d\n", j);
}
该错误意味着,尽管编译器知道j
是什么,但最终构建过程(ld
)没有在任何地方找到j
的实际定义
你说
在上面的程序变量j
中,刚刚声明,未定义
否,在您的程序中定义了j
int*i,j
是声明还是定义
这是两个变量的定义。它定义类型为int
的j
,类型为int*
的i
,或指向-int
的指针
看起来您已经开始使用指针了,当您使用指针时,您必须更仔细地考虑内存分配。(您可能还需要考虑静态和动态分配之间的区别。)
首先要了解的是,编译器完全能够分配内存。编译器始终为变量分配内存。只有当您开始使用指针时,您才需要开始担心内存分配,并自行分配内存
正如我们所说,这条线
int *i;
这是一个定义。它说明指针指向-int
类型的名为i
的变量的类型,并为其分配空间
但在本例中,我们分配的空间是指针。我们没有为指针指向的内容分配任何空间。事实上,这个指针还没有指向任何地方:它还未初始化
如果我们说
int j;
int *i = &j;
int *i = malloc(sizeof(int));
现在指针i
确实指向某个地方:它指向变量j
。现在,我们不仅为指针i
分配了内存,还为指针指向分配了内存
为指向的指针分配内存的另一种方法是动态内存分配,通常通过调用malloc
。如果我们说
int *i = malloc(sizeof(int));
我们再次为i
和它所指向的内容分配了内存。我们让编译器为i
分配内存,并调用malloc
为i
动态分配内存
一些图片可能会有帮助。以下是第一段代码后的情况:
+-----------+
j: | |
+-----------+
^
|
+-----|-----+
i: | * |
+-----------+
+-----------+ +-----------+
i: | *-------------> | |
+-----------+ +-----------+
这两个框都是由编译器分配给我们的
下面是第二段代码后的情况:
+-----------+
j: | |
+-----------+
^
|
+-----|-----+
i: | * |
+-----------+
+-----------+ +-----------+
i: | *-------------> | |
+-----------+ +-----------+
左边的i
框是编译器分配给我们的,右边的未命名框是我们从malloc
获得的
申报怎么样?什么是
extern int j;
看起来像?我想我会这样画:
j:
有一个符号(一个名称)j
,但旁边还没有一个方框(尽管如果有方框,它的大小和形状应该适合容纳int
)
在你询问的评论中 给定
intj;int*i=&j
我们不知道j
的内存位置,因此如何将其地址分配给i
我不知道你说的“我们不知道j
的内存位置”是什么意思。我们可能不知道地址,但编译器知道。编译器会尽一切努力确保在已知位置为j
分配空间。表达式&j
字面意思是“获取变量j
的已知位置”。自从
int j;
是一个定义,它意味着j
将在已知位置分配空间
在所有这一切中,我一直在说“编译器为…分配内存”,但实际上它比这要复杂一点。实际内存的实际分配可能会在以后进行 对于局部变量,编译器在堆栈上“分配”变量。它实际上(通常)做的是在函数的堆栈框架中留出空间。从某种意义上说,局部变量的“地址”是它与堆栈帧底部的偏移量。在程序运行、调用函数并在堆栈上的特定地址创建其堆栈帧之前,变量的实际地址是未知的
int *i = &j;