我不是C程序员,所以请谅解;)
C语言具有指针及其所有优点。但是原始类型声明是如何工作的?
例如,我可以做到:
char x = 'a';
那里没有指针,但是值必须存储在内存中的某个地方,对吗?我可以认为上述声明翻译为:
char* _x = malloc(sizeof(char));
char x = *_x;
答案 0 :(得分:4)
不,你不能。
malloc(sizeof(char));
将在堆中分配内存,您将负责删除它。这样做的好处之一是,分配的内存中的数据在作用域结束时不会“死亡”,只有在销毁数据时才会死亡。
char c = 'a'
将存储在堆栈中,并且在作用域结束时将自动释放。
编辑:关于您的评论,通常,局部变量通常将存储在堆栈中(这当然是自动的)。 malloc , calloc
允许您“询问”堆中的空间,并根据需要使用它。如果您需要更多信息,可以查看here,如@Jabberwocky
答案 1 :(得分:2)
那里没有指针,但是值必须存储在内存中的某个地方,对吗?
在这种特定情况下(char x = 'a';
),该值可能实际上仅存储在处理器寄存器中。但是程序的行为"as-if" x
位于某个内存位置。
在实践中,请阅读How To Debug Small Programs并浏览一些C reference网站。如果您想更准确地理解C11的(棘手的)semantics,请参考其标准n1570,并研究Compcert项目和{{3}这样的静态源代码分析器}。 C的Frama-C很棘手。
还请阅读有关Memory semantics,它们的automatic variables和scope的信息。另请参阅有关call stack说明符(auto
是默认存储期限)。花时间了解什么是storage class,并成为undefined behavior。
PS。您的虚构代码缺少一些free(_x)
,这确实很重要,您应该问自己_x
存储在哪里!但是不要指望我们教您C(需要整本书)。
答案 2 :(得分:1)
这里
char x = 'a';
那里没有指针,但是值必须存储在内存中,对吧?是的,没有指针,但是x
是局部变量,并且存储在stack
中主内存部分,即x
确实具有有效的内存。
我是否可以将上述声明翻译为:char * _x = malloc(sizeof(char));
char x = * _x;
不,您不能因为x
部分分配了heap
。因此,您不能认为这两种情况都相同。 *_x
拥有什么呢?垃圾。您需要在分配内存后再添加一条语句
*_x = 'a';
答案 3 :(得分:1)
你不在乎。
您需要知道的是
a := []int{0,1,2,3,4}
nextPermutation, exists := iterPermutation(a)
for exists {
nextPermutation()
}
func iterPermutation(a []int) []int {
return func() []int {
i := len(a) - 2
for i >= 0 && a[i+1] <= a[i] {
i--
}
if i < 0 {
return a
}
j := len(a) - 1
for j >= 0 && a[j] <= a[i] {
j--
}
a[i], a[j] = a[j], a[i]
for k, l := i, len(a)-1; k < l; k, l = k+1, l-1 {
a[k], a[l] = a[l], a[k]
}
return a
}
}
将char x = 'a';
声明为具有自动存储持续时间的x
类型,并为其设置char
常量int
,其值取决于在平台上使用的 encoding 上,但一定不能溢出'a'
。
能否在编译中幸存完全是另一回事。每当您在源代码中编写char
时,编译器可能会用数字'a'
代替;特别是如果x
从未改变过?
答案 4 :(得分:1)
这是一个简单的问题,答案很复杂。
实际上,您在问两个不同的问题-如何为变量分配存储空间,以及变量的名称与该存储空间如何关联。
对于第一个问题,C language definition没有指定变量的存储方式的分配机制,具体取决于编译器executable file format和操作系统。您会听到人们谈论“堆栈”和“堆”,但是C语言定义中没有什么强制使用堆栈或堆来管理变量和其他对象。
关于第二个问题,答案(通常)是“不是”。变量名称未保留在生成的机器代码中。取而代之的是,机器代码通常将通过与寄存器中存储的某个地址的偏移量来引用该对象。