引自免费微信小程序:皆我百晓生
首先,让我们分析并详细解释代码中指针数组输出的各种地址:
int n=3;
char *str[n]; // 定义一个包含3个指向字符的指针数组
// 分配内存给每个指针,并尝试读取字符串
for(int i=0; i<n;i++)
{
str[i]=(char*)malloc(sizeof(char)); // 分配一个字节的内存,通常不足以存储整个字符串
char ch=scanf("%s",str[i]); // 这里试图读取一个字符串到分配的内存空间,但分配的空间太小,可能导致内存溢出
}
// 输出各种地址信息
for(int i=0;i<n;i++){
printf("str[%d]=%s\tstr[%d]=%p\t&str[%d]=%p\t*str[%d]=%p\n",i,str[i],i,str[i],i,&str[i],i,*str[i]);
}
对于输出的部分,有以下几点需要理解:
-
str[i]
:
- 这是在输出字符串内容。由于你只分配了一个字节给每个
str[i]
指向的内存区域,且没有为字符串末尾添加空字符 \0
,所以这里的 %s
输出可能会导致未定义行为或者输出不完整的字符串。
-
str[i]=%p
:
%p
是格式化字符串,用于输出指针变量的值,也就是每个 str[i]
指针所指向的内存地址。
-
&str[i]
:
- 这是在输出
str[i]
指针本身的地址。&
是取址运算符,它返回的是存放指针变量的地址,而不是指针所指向的地址。
-
*str[i]=%p
:
- 此处是错误的表达方式,因为
%p
需要一个指针作为参数,而 *str[i]
实际上是解引用操作,访问 str[i]
所指向的内存中的第一个字符。此处应该用 %c
来输出字符,而非 %p
。但由于之前仅分配了一个字节,且未初始化,此部分输出同样具有未定义行为。
修正后的代码应增加字符串所需的实际内存大小,并确保正确使用 %c
输出字符和避免未初始化的内存读取。同时,为了安全起见,应在使用完内存后释放它。
修正后的示例(假设我们分配足以容纳一个小字符串的内存):
#include <stdio.h>
#include <stdlib.h>
int main() {
int n = 3;
char *str[n];
for(int i = 0; i < n; i++) {
str[i] = (char*)malloc(10 * sizeof(char)); // 分配足够存储短字符串的空间
if (!str[i]) {
perror("Failed to allocate memory");
exit(EXIT_FAILURE);
}
scanf("%9s", str[i]); // 使用更安全的方式限制输入长度
}
// 输出正确的地址和字符串
for(int i = 0; i < n; i++) {
printf("str[%d]=%s\tstr[%d]=%p\t&str[%d]=%p\t*(str[%d])=%c\n",
i, str[i], i, str[i], i, &str[i], i, *str[i]);
}
// 释放内存
for(int i = 0; i < n; i++) {
free(str[i]);
}
return 0;
}
现在,根据修正后的代码,输出将展示:
str[i]
:存储在 str[i]
指向内存位置的字符串内容。str[i]=%p
:str[i]
指针指向的内存地址。&str[i]=%p
:str[i]
指针本身的地址。*(str[i])=%c
:str[i]
指向的第一个字符。