通过指针访问值之程序声明一个指针和一个变量,然后输出它们的地址和它们所含的值

本文详细介绍了C语言中指针的基本概念,包括间接运算符、指针初始化、内存地址输出等,并通过具体示例展示了如何使用指针进行变量操作。

注意:1间接运算符*可以访问指针所指向的变量值,这个运算符也称为取消引用运算符,应为它用于取消对指针的引用。

2.注意要初始化指针,int *p=NULL;
3.%p表示输出的是变量的地址,应使用输出格式说明符%p,它以16进制的格式输出内存地址

4

格式符z和整数转换说明符一起使用,表示对应数字是一个size_t值。属于C99。

%ld 表示long型
5指针变量本身所占用的字节数只与编译器与操作系统有关是它指向的对象的类型无关
6用(void*)&pnumber将禁止编译器发出警告,应为%需要的是某种指针类型的变量,但&pnumber的类型是指向int指针的指针

#include <stdio.h>
main(void){
	int number=0;
	int *pnumber=NULL;
	number=10;
	printf("number's address:%p\n",&number);
	printf("number's value:%d\n\n",number);
	pnumber=&number;
	printf("pnumber's address:%p\n",&pnumber);
	printf("pnumber's value:%d\n",pnumber);
	printf("pnumber's size: %zd bytes\n",sizeof(pnumber));
	printf("value pointed to:%d\n",*pnumber);
	return 0;

}


此时指针占用了8个字节,地址包含16进制的数字,这是应为本例所用的计算机采用64位操作系统,且支持64位地址,一些编译器只支持32地址,此时的地址是32位的


<think>我们讨论的是C语言中字符串字面量初始化数组指针时,数组名指针的不同。 根据引用[1]引用[2]: - 当我们使用字符串字面量初始化字符数组时,如:`char heart[] = "I love Tillie!";`,实际上是将字符串字面量的内容(包括结尾的空字符'\0')复制到新分配的数组中。因此,数组名`heart`代表的是这个数组的首地址,但数组本身存储在栈或全局区(取决于声明位置),并且数组的内容是可修改的(除非声明为const)。 - 当我们使用字符串字面量初始化字符指针时,如:`const char *head = "I love Millie!";`,这里指针`head`被赋为字符串字面量在内存中的地址。字符串字面量存储在程序的只读数据段(例如.rodata段),因此尝试通过指针修改字符串字面量的内容会导致未定义行为(通常程序会崩溃)。所以通常我们会加上`const`修饰符。 那么为什么数组名指针不同呢? - 虽然它们都指向一个内容相同的字符串,但是它们指向的是不同的内存区域。 - 数组`heart`的内存是独立分配的,它拥有字符串字面量的一个副本。所以数组名`heart`的(即数组首地址)是副本的地址。 - 指针`head`直接指向字符串字面量的原始地址(在只读段)。 因此,即使字符串内容相同,数组名指针(即它们所指向地址)在绝大多数情况下是不同的(除非编译器做了优化,将相同的字符串字面量合并存储,但即使合并,数组初始化时还是会复制一份到可写区域,所以数组的地址还是字面量地址不同)。 另外,引用[3]说明了字符数组初始化的方式,编译器会自动添加空字符,并且数组的大小由字符串长度决定(包括空字符)。 引用[4]进一步强调了指针指向字符串字面量的缺点:不能修改,而数组可以修改(除非声明为const数组)。 总结: - 数组初始化:复制字符串字面量到数组,数组在可写内存区域,地址为新分配内存的地址。 - 指针初始化:直接指向字符串字面量所在的内存地址(只读段),所以指针就是字符串字面量的地址。 因此,数组名指针地址)不同,因为它们指向的是不同的内存位置。 注意:在C语言中,数组名在大多数表达式中会退化为指向数组首元素的指针,但这里我们讨论的是它们存储的地址(即数组首元素的地址指针变量存储的地址)不同。 下面用代码示例说明: ```c #include <stdio.h> int main() { char heart[] = "I love Tillie!"; const char *head = "I love Millie!"; // 打印地址 printf("heart: %p\n", (void*)heart); // 输出数组的地址(可写) printf("head: %p\n", (void*)head); // 输出字符串字面量的地址(只读) // 注意:两个字符串字面量内容不同,所以地址肯定不同。即使相同,也可能不同(但编译器可能合并相同的字面量,但数组初始化会复制,所以数组地址还是不同) // 为了说明问题,我们使用相同的字符串字面量 const char *head2 = "I love Tillie!"; char heart2[] = "I love Tillie!"; printf("head2: %p\n", (void*)head2); // 指向字面量地址 printf("heart2: %p\n", (void*)heart2); // 指向数组的地址,与head2不同 return 0; } ``` 运行上述代码,我们会发现`heart2``head2`的地址)是不同的。 原因: - `head2`指向的是字符串字面量"I love Tillie!"的存储地址(在只读段)。 - `heart2`是一个数组,它被初始化时,编译器将字符串字面量的内容复制到数组`heart2`中,因此`heart2`的地址是栈上(或全局区)新分配的数组的地址。 所以,数组名指针不同,因为数组存储的是字符串的副本,而指针直接指向原始字符串字面量。 引用文献: [^1]: 初始化字符数组指针的区别。 [^2]: 字符串字面量与字符串变量的区别,指针指向的内容只读。 [^3]: 使用字符串字面量初始化字符数组,编译器自动添加空字符。 [^4]: 指针数组的缺点,不能修改字符串字面量,而字符数组可以修改(除非声明为const)。</think>在C语言中,使用字符串字面量初始化字符数组字符指针时,数组名指针不同的根本原因在于**内存分配方式****语义差异**。以下是关键区别: --- ### 一、内存分配与存储位置 1. **字符数组初始化** ```c char heart[] = "I love Tillie!"; ``` - 编译器在栈或静态存储区分配**独立内存空间**(长度=字符串长度+1) - 将字符串字面量内容(包括终止符`\0`)**复制**到新分配的内存中[^3] - 数组名`heart`是**常量地址**,代表数组首元素位置(不可修改) 2. **字符指针初始化** ```c const char *head = "I love Millie!"; ``` - 字符串字面量存储在**只读数据段**(`.rodata`) - 指针变量`head`在栈上分配,存储**字面量的内存地址** - `head`本身是变量,可指向其他地址(但指向的内容只读)[^2][^4] --- ### 二、差异的本质 | 特性 | 字符数组 (`heart`) | 字符指针 (`head`) | |--------------|--------------------------|----------------------------| | **内存来源** | 独立分配的副本 | 只读段的原始字面量地址 | | **地址类型** | 数组首地址(常量) | 指针变量存储的地址(可变) | | **可修改性** | 内容可修改 | 内容不可修改(只读)[^4] | | **大小计算** | `sizeof(heart)`=实际长度 | `sizeof(head)`=指针大小 | --- ### 三、示例验证 ```c #include <stdio.h> int main() { char heart[] = "I love Tillie!"; const char *head = "I love Millie!"; // 地址对比(通常不同) printf("heart 地址: %p\n", (void*)heart); // 0x7ffd42a1b320(栈地址) printf("head 地址: %p\n", (void*)head); // 0x4006a4(只读段地址) // 大小对比 printf("sizeof(heart): %zu\n", sizeof(heart)); // 15(含'\0') printf("sizeof(head) : %zu\n", sizeof(head)); // 8(指针大小) // 修改性测试(数组可修改,指针引发段错误) heart[0] = 'i'; // 合法 // head[0] = 'i'; // 运行时错误 } ``` --- ### 四、根本原因总结 1. **语义不同** - 数组声明:**创建存储空间**并初始化内容 - 指针声明:**引用现有存储空间**(字面量) 2. **内存位置不同** - 数组副本在可写区域(栈/静态区) - 字面量原始在只读段 3. **类型系统差异** - 数组名在表达式中退化为地址常量 - 指针是存储地址变量[^1] > 关键结论:数组初始化是**复制语义**,指针初始化是**引用语义**,导致二者地址不同[^2][^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值