我是C的新手,目前我正在努力了解指针是如何工作的。
这是一个令我困惑的问题:
据我所知,在为指针赋值之前,你应该为该指针分配一定的内存(如果我错了,请纠正我:)),如下面的代码:
int main(void) {
int i;
int * ptr = (int *)malloc(sizeof(int));
i = 2;
*ptr = 5;
printfn("%d",*ptr);
free(ptr);
}
但是,在C中声明字符串时,就像:
char *p = "Hello world";
无需分配内存。
原因是什么?它是如何运作的?如果我遗失了什么,请提醒我。
答案 0 :(得分:8)
char *p = "Hello world";
你创建了一个指针并将其指向一个常量字符串。编译器将其放在标记为只读的内存中。
它没有名称,并且具有静态存储持续时间(意味着它在程序的整个生命周期中存在);以及一个名为p
的指向char的类型的变量,它使用该未命名的只读数组中第一个字符的位置进行初始化。
答案 1 :(得分:4)
"Hello world"
是静态数据,会被编译到您的二进制文件中,就像示例中的2
和5
一样。
char * p
被定义为指向二进制文件中该位置的指针。
这也是 char const
的原因,因为您不应该写到该位置。 (你的编译器应该给你一个警告。)
答案 2 :(得分:2)
...你应该为那个指针分配一些内存......
不,你似乎误解了指针...
指针是保存某些类型的地址的类型。看看这个例子。
int a = 1;
int *p = &a;
a
的类型为int
,其中包含整数。
p
的类型为int *
,其中包含整数变量的地址。
让我们假设这样的记忆:
--------------------------------------
variables: | a | p |
--------------------------------------
address : | 0x12341234 | 0x12341238 |
--------------------------------------
&
运算符获取操作数的地址。因此,&a
等于0x12341234
。
所以变量初始化如下:
--------------------------------------
variables: | a | p |
--------------------------------------
address : | 0x12341234 | 0x12341238 |
--------------------------------------
value : | 1 | 0x12341234 |
--------------------------------------
现在,查看此代码*p
。 *
运算符解除引用运算符,获取指针所指向的变量的值。在这种情况下,p
包含0x12341234
- 0x12341234
中有哪些变量? a
!因此*p
等于1
所包含的a
。
现在看一下这个例子:
#include <stdlib.h>
char c1 = '1';
int main()
{
char c2 = '2';
char *p1 = &c1;
char *p2 = &c2;
char ar[13] = "hello world!"; /* don't forget '\0' : 12 + 1. */
char *p3 = &ar[0];
const char *p4 = "hello world!"; /* notice the type, `const char *` */
char *p5 = malloc(13 * sizeof(char));
}
c1
是全局变量,因此编译器直接将它放在程序的数据部分上。 c2
是main
的局部变量,因此main
将其置于堆栈上。无论如何,他们被置于记忆中。 p1
和p2
包含地址,因此*p1
为'1'
(c1
),*p2
为{ {1}}('2'
)。
c2
是ar
的13长数组。它放在这样的记忆中:
char
------------------------------------------------------
|'h'|'e'|'l'|'l'|'o'|' '|'w'|'o'|'r'|'l'|'d'|'!'|'\0'|
------------------------------------------------------
是&ar[0]
的第一个元素的地址,因此ar
包含p3
的地址。
现在看看'h'
。它由p4
初始化。你的问题是它被分配的地方 - 它只是(字符串)常量,如"hello world!"
,1234
或2.71
。常量由编译器直接放在程序上。与'a'
类似,字符串常量直接放在程序的 ro 数据部分上。与数据部分对比, rodata部分是只读的(只读数据),因为字符串常量是常量。 (如您所知,常量是只读的。)因此c1
的类型为p4
。
const char *
由p5
的返回值初始化,即来自动态分配。在这种情况下,malloc
会在某处分配内存,malloc
由此初始化。